/* =====================================================================
   Nextdoor Logistics — design system
   Heavily inspired by maersk.com: light-weight headings, deep near-black
   text on white, one calm green accent, image-led cards, thin inline icons,
   square-ish controls and a lot of white space. No gradients.
   ===================================================================== */

/* Inter, self-hosted so the site is fully offline and makes no third-party
   request. Inter ships as a variable font: one file per subset covers the whole
   100-900 range, which is why there are two files and not one per weight.
   latin-ext is not optional here, the cedi sign (GH₵, U+20B5) lives in it.
   Re-download from the Google Fonts CSS if Inter is ever updated. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Maersk palette.
     Deep Blue is the "black": text, dark blocks. Maersk Blue is the accent and
     the primary button fill (always with deep-blue text on it, as they do). */
  /* Palette taken from bragusa.org: a deep forest green as the dark, a muted
     sage as the accent, over warm off-white rather than pure white. This
     replaced the Maersk blues; the Maersk influence now lives in the layout,
     the light headings and the control shapes, not the colour. */
  --ink: #062d28;            /* BRAG deep green: text, dark bands, primary fill */
  --paper: #ffffff;
  --tint: #eef2ef;           /* pale green wash: sections, footer */
  --tint-2: #d3ded6;         /* pale green border */
  --tile: #b9cbbf;           /* saturated light green behind illustrations */
  --grey: #dbd9d3;           /* warm neutral ground (BRAG stone) */

  --brand: #698071;          /* BRAG sage: accents, active states, icons */
  --brand-strong: #40584b;   /* deeper sage for link text (7.7:1 on white) */

  /* The one warm note in the system, and the only colour allowed to shout.
     Reserved for the primary call to action. Sage was tried here first and read
     flat and washed out against the deep green; this picks up the warm side of
     BRAG's palette (their stone and olive) and pushes it to full saturation.
     Deep green on it measures 7.9:1, so it stays legible while it grabs. */
  --accent: #e8b13a;
  --accent-hover: #f2c04f;
  --brand-deep: #062d28;     /* deep green */

  /* neutrals derived from ink over paper */
  --ink-90: rgba(6, 45, 40, 0.90);
  --ink-70: rgba(6, 45, 40, 0.68);
  --ink-55: rgba(6, 45, 40, 0.55);
  --ink-40: rgba(6, 45, 40, 0.38);
  --ink-15: rgba(6, 45, 40, 0.15);
  --ink-10: rgba(6, 45, 40, 0.10);
  --ink-06: rgba(6, 45, 40, 0.06);
  --ink-03: rgba(6, 45, 40, 0.035);

  --paper-70: rgba(255, 255, 255, 0.72);
  --paper-55: rgba(255, 255, 255, 0.58);
  --paper-15: rgba(255, 255, 255, 0.16);
  --paper-10: rgba(255, 255, 255, 0.10);

  --line: #dde4df;
  /* Measured off maersk.com: their controls sit at a 5px radius, not the
     near-square 2px this file previously assumed. 4px keeps the squared-off
     character while matching their softness. */
  --radius: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  /* Buttons are rounder than the other controls, matching the Maersk button
     the client supplied: a soft rounded rectangle, not a square or a pill. */
  --radius-btn: 8px;

  --shadow-sm: 0 1px 2px rgba(6, 45, 40, 0.06);
  --shadow-md: 0 8px 24px -12px rgba(6, 45, 40, 0.18);
  --shadow-lg: 0 18px 48px -18px rgba(6, 45, 40, 0.22);

  --container: 1200px;
  --gutter: 32px;      /* page side padding; full-bleed rows negate this */
  --header-h: 116px;

  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    Helvetica, Arial, sans-serif;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* Smooth scrolling for in-page jumps and any scripted scrollTo.
     Turned off automatically under prefers-reduced-motion (see the bottom of
     this file). */
  scroll-behavior: smooth;
  /* The header is sticky, so an anchor landing at y=0 would sit underneath it.
     Reserve the announcement bar plus the masthead, with a little breathing
     room, so jumped-to content starts clear of the chrome. */
  scroll-padding-top: calc(var(--announce-h, 0px) + 92px);
}

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.6;
  font-size: 16px;
  letter-spacing: -0.003em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

h1, h2, h3, h4 { margin: 0; font-weight: 400; letter-spacing: -0.012em; line-height: 1.18; }
p { margin: 0; }

::selection { background: var(--ink); color: var(--paper); }

/* ------------------------------------------------------------- layout */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: 76px; }
.section--tight { padding-block: 52px; }
.section--tint { background: var(--tint); }

.eyebrow {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-55);
}

.lead { font-size: 17px; color: var(--ink-70); line-height: 1.65; max-width: 62ch; }
.muted { color: var(--ink-55); }

/* Maersk type scale: large, light, generous. Never bold. */
.display {
  font-size: clamp(34px, 4.6vw, 56px);
  font-weight: 400;
  letter-spacing: -0.018em;
  line-height: 1.14;
}
.h-xl { font-size: clamp(26px, 3vw, 40px); font-weight: 400; letter-spacing: -0.014em; line-height: 1.2; }
.h-lg { font-size: clamp(19px, 2vw, 24px); font-weight: 400; line-height: 1.3; }

/* ----------------------------------------------------------- buttons
   Maersk's hierarchy, mapped to where each one belongs:
     .btn            deep-blue fill, white text  -> the main action on a light
                     surface (Track, Get a quote, Log package, Send message)
     .btn--accent    Maersk Blue fill, deep-blue text -> high-visibility CTA in
                     the header, and the Delivered status
     .btn--outline   hairline border, ink text   -> secondary on light
     .btn--light     white fill, ink text        -> primary on dark imagery
     .btn--onDark-outline  white hairline        -> secondary on dark
   Disabled is a flat grey, as Maersk shows Track before you type.
   No gradients, no lift, no shadow. */
.btn {
  --btn-bg: var(--ink);
  --btn-fg: #fff;
  --btn-bd: transparent;
  --btn-bg-h: #0d453d;      /* lifts slightly on hover, as Maersk's dark does */
  --btn-bd-h: transparent;
  --btn-fg-h: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Height is set rather than derived from padding so a button always matches
     the input sitting next to it, whatever the label does. */
  height: var(--btn-h, 46px);
  padding: 0 22px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--btn-bd);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease), border-color 0.18s var(--ease);
  white-space: nowrap;
}
.btn:hover { background: var(--btn-bg-h); border-color: var(--btn-bd-h); color: var(--btn-fg-h); }
.btn:active { transform: translateY(0.5px); }

/* The primary call to action: warm amber carrying deep-green text. This is the
   Maersk pattern (bright fill, dark label) applied to our own accent, and it is
   deliberately the loudest thing on any page. Use it sparingly. */
.btn--accent, .btn--cta {
  --btn-bg: var(--accent); --btn-fg: var(--ink); --btn-bd: transparent;
  --btn-bg-h: var(--accent-hover); --btn-bd-h: transparent; --btn-fg-h: var(--ink);
  font-weight: 600;
}

/* disabled: flat grey, no pointer. Used for Track until a number is entered. */
.btn[disabled], .btn:disabled {
  background: #e6eae7 !important;
  color: var(--ink-40) !important;
  border-color: transparent !important;
  cursor: not-allowed;
}
.btn[disabled] .arrow { transform: none !important; }

/* Secondary on light (Maersk's "Contact us"). The border used to be --ink-40,
   which at 38% opacity read so much lighter than the filled button beside it
   that the pair looked mismatched in size. Both variants have always measured
   the same box; this just gives the outline equal presence. */
.btn--outline {
  --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--ink-55);
  --btn-bg-h: var(--ink-06); --btn-bd-h: var(--ink); --btn-fg-h: var(--ink);
}
/* on dark imagery: solid white, and a white hairline variant */
.btn--light {
  --btn-bg: #fff; --btn-fg: var(--ink); --btn-bd: #fff;
  --btn-bg-h: var(--tint); --btn-bd-h: var(--tint); --btn-fg-h: var(--ink);
}
.btn--onDark-outline {
  --btn-bg: transparent; --btn-fg: #fff; --btn-bd: rgba(255,255,255,0.65);
  --btn-bg-h: #fff; --btn-bd-h: #fff; --btn-fg-h: var(--ink);
}

.btn--ghost {
  --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: transparent;
  --btn-bg-h: var(--tint); --btn-bd-h: transparent; --btn-fg-h: var(--brand-strong);
}

.btn--sm { --btn-h: 40px; padding: 0 16px; font-size: 14.5px; }
.btn--lg { --btn-h: 54px; padding: 0 30px; font-size: 17px; }
.btn--block { width: 100%; }

.btn .arrow { transition: transform 0.18s var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

.textlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
  color: var(--brand-strong);
  transition: color 0.18s, gap 0.18s;
}
.textlink:hover { color: var(--brand-deep); gap: 10px; text-decoration: underline; text-underline-offset: 3px; }

/* ========================================================== TOP CHROME */

/* announcement bar — sticks to the top alongside the nav */
.announce {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--ink);
  color: var(--paper);
  font-size: 13.5px;
  letter-spacing: 0.01em;
}
.announce__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 9px 48px 9px 32px;
  position: relative;
  text-align: center;
}
.announce__inner strong { font-weight: 650; }
.announce a { border-bottom: 1px solid var(--paper-55); padding-bottom: 1px; }
.announce__close {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  color: var(--paper-70);
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.2s, color 0.2s;
}
.announce__close:hover { background: var(--paper-15); color: var(--paper); }
.announce[hidden] { display: none; }
/* The editor's live preview: the real bar, but parked in the page rather than
   stuck to the top, and always showing the full-width wording. */
.announce--preview { position: static; border-radius: var(--radius); }
.announce--preview .announce__inner { padding-inline: 18px; }
.announce--preview .announce__short { display: none; }
.announce--preview .announce__long { display: inline; }

/* icon button (staff login) sitting beside the Get Quote CTA.
   Both are pinned to --control-h so the square icon and the text button are
   exactly the same height and share a baseline, rather than each being sized
   by its own padding. */
.iconbtn {
  display: inline-grid;
  place-items: center;
  width: var(--control-h, 38px);
  height: var(--control-h, 38px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink-70);
  flex-shrink: 0;
  transition: color 0.18s, border-color 0.18s, background 0.18s;
}
.iconbtn:hover { color: var(--brand); border-color: var(--brand); background: var(--tint); }

/* main header */
.masthead {
  position: sticky;
  /* sits directly under the sticky announcement bar (0 when dismissed) */
  top: var(--announce-h, 0px);
  z-index: 50;
  /* solid white like JB Hunt; no blur (it also breaks sticky compositing) */
  background: #fff;
  border-bottom: 1px solid var(--line);
  transition: box-shadow 0.25s var(--ease);
}
.masthead.is-stuck { box-shadow: 0 1px 3px rgba(6, 45, 40, 0.10); }

.masthead__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  height: 76px;
}

.brand { display: inline-flex; align-items: center; gap: 11px; flex-shrink: 0; }
.brand__mark { height: 30px; width: auto; }
.brand__type {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.brand__type b { font-weight: 700; }

/* primary nav */
.nav { display: flex; align-items: center; gap: 2px; }
.nav a {
  position: relative;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-70);
  padding: 9px 14px;
  border-radius: var(--radius);
  transition: color 0.2s, background 0.2s;
}
/* Every link carries the amber rule, wiped in from the left on hover and held
   open for the current page. The previous hover only nudged the text from
   ink-70 to a mid sage, a shift too small to read as a response at all. */
.nav a::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 2px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.22s var(--ease);
}
.nav a:hover { color: var(--ink); background: transparent; }
.nav a:hover::after,
.nav a:focus-visible::after { transform: scaleX(1); }
.nav a[aria-current='page'] { color: var(--ink); font-weight: 600; }
.nav a[aria-current='page']::after { transform: scaleX(1); }

.masthead__right {
  --control-h: 38px;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}
/* equal height, vertically centred against the icon button */
.masthead__right .btn {
  height: var(--control-h);
  padding-block: 0;
}
.contactinfo { text-align: right; line-height: 1.2; }
.contactinfo__label {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.contactinfo__num { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

/* hamburger */
.hamburger {
  display: none;
  flex-direction: column;
  gap: 5px;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
}
.hamburger span {
  width: 20px; height: 2px; background: var(--ink); border-radius: 2px;
  transition: transform 0.25s var(--ease), opacity 0.2s;
}
.hamburger.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger.is-open span:nth-child(2) { opacity: 0; }
.hamburger.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ============================================================== HERO
   Maersk pattern: full-bleed photo, dark scrim for legibility, text on the
   left, and a white utility card overlapping the bottom edge.
   Drop a photo in with:  <div class="hero__media"><img src="..." alt=""></div>
   Until then the scrim alone gives a clean dark block. */
.hero {
  position: relative;
  background: var(--ink);
  color: #fff;
  overflow: hidden;
}
.hero__media { position: absolute; inset: 0; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero::before {
  content: '';
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(6,45,40,0.92) 0%, rgba(6,45,40,0.72) 45%, rgba(6,45,40,0.30) 100%);
}
.hero__inner {
  position: relative;
  z-index: 2;
  max-width: 640px;
  padding-block: 92px 150px;   /* room for the overlapping card */
}
.hero .eyebrow { color: rgba(255,255,255,0.75); }
.hero h1 { color: #fff; margin-top: 16px; }
.hero__sub { color: rgba(255,255,255,0.85); font-size: 17px; margin-top: 18px; max-width: 52ch; }
.hero__cta { display: flex; gap: 12px; margin-top: 28px; flex-wrap: wrap; }

/* The ship sits centre-right in the frame, so the photo is oversized inside its
   box to push the vessel clear of the text column. The box itself stays flush
   to both edges: offsetting it instead left a bare band down the left with a
   hard vertical seam where the photo began.
   (A pale .hero--light variant used to live here, for a washed-out photograph
   that has since been replaced. The current cover is a deep teal ocean and
   takes the standard dark scrim above.) */
.hero .hero__media img { width: 124%; max-width: none; object-position: 60% center; }

/* Below 1080px .hero__inner drops its max-width and the copy runs the full
   width, so a left-to-right wash stops protecting the last line. Switch to a
   top-to-bottom wash and bring the whole vessel back into frame. */
@media (max-width: 1080px) {
  /* The hero is far taller than the photo's 16:9, so `cover` crops it hard
     sideways. 33% keeps the stern inside the frame with the bow running off to
     the right, rather than slicing the vessel at both ends. */
  .hero .hero__media img { width: 100%; object-position: 33% center; }
  .hero::before {
    background: linear-gradient(180deg,
      rgba(6,45,40,0.62) 0%,
      rgba(6,45,40,0.70) 55%,
      rgba(6,45,40,0.80) 100%);
  }
}

/* white utility card that overlaps the hero, like Maersk's tracking panel */
.herocard {
  position: relative;
  z-index: 3;
  margin-top: -104px;
  background: #fff;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 0 0 22px;
}
.herocard__tabs {
  display: flex; gap: 4px; padding: 0 8px;
  border-bottom: 1px solid var(--line);
}
.herocard__tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 16px 16px 14px;
  font-size: 14.5px; font-weight: 500; color: var(--ink-70);
  border: 0; background: transparent; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color 0.18s, border-color 0.18s;
}
.herocard__tab:hover { color: var(--ink); }
.herocard__tab[aria-selected='true'] { color: var(--ink); border-bottom-color: var(--brand); }
.herocard__panel { padding: 22px 22px 0; }
.herocard__panel[hidden] { display: none; }
.herocard__row { display: flex; gap: 12px; align-items: flex-end; }
.herocard__row .field { flex: 1; margin: 0; }
/* The search field matches its button. The .btn--lg beside it stands 54px while
   the input's padding gave it 44, so the two sat on the same baseline with the
   button a clear 10px taller. */
.herocard__row .input,
.herocard__row .select { height: 54px; padding-block: 0; font-size: 15.5px; }
.herocard__note { font-size: 13px; color: var(--ink-55); margin-top: 12px; }

/* circular outline arrows (carousel controls) */
.roundbtn {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--ink-40); background: transparent; color: var(--ink);
  display: grid; place-items: center; cursor: pointer;
  transition: border-color 0.18s, background 0.18s;
}
.roundbtn:hover { border-color: var(--ink); background: var(--ink-06); }
.roundbtn[disabled] { opacity: 0.35; cursor: default; }

/* ====================================================== AUTH (standalone)
   The staff login renders without the site header or footer: just the form
   on a calm tinted field, with a way back to the site. */
.authpage {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 32px 20px;
  background: var(--tint);
}
.authpage__inner { width: 100%; max-width: 400px; }
.authpage .panel { background: #fff; }
.authpage__brand {
  display: inline-flex; align-items: center; gap: 10px;
  justify-content: center; width: 100%; margin-bottom: 20px;
}
.authpage__back { text-align: center; margin-top: 18px; }

/* ============================================================== FORMS */
.field { margin-bottom: 16px; }
.field:last-child { margin-bottom: 0; }
.field label {
  display: block; font-size: 12.5px; font-weight: 500; letter-spacing: 0.01em;
  color: var(--ink-70); margin-bottom: 7px;
}
.field .hint { font-size: 12px; color: var(--ink-55); margin-top: 6px; }
/* required-field asterisk, clearly red so it reads as required */
.req { color: #c0392b; font-weight: 700; }

/* about page: principle card icon, thin sage in a soft tinted circle */
.principle__icon {
  display: inline-grid; place-items: center; width: 48px; height: 48px;
  border-radius: 50%; background: var(--tint); color: var(--brand-strong); margin-bottom: 16px;
}

.input, .select, .textarea {
  width: 100%;
  padding: 12px 14px;
  font-size: 15px;
  font-family: inherit;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink-15);
  border-radius: var(--radius);
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
  appearance: none;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--ink-10);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-40); }
.textarea { resize: vertical; min-height: 110px; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23151414' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
}

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* password field with show/hide toggle */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-right: 46px; }
.pw-toggle {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; border: 0; background: transparent; cursor: pointer;
  display: grid; place-items: center; color: var(--ink-55); border-radius: var(--radius);
}
.pw-toggle:hover { color: var(--ink); background: var(--tint); }

/* segmented control (Air / Sea) */
.segment { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; background: var(--ink-06); padding: 4px; border-radius: var(--radius); }
.segment input { position: absolute; opacity: 0; pointer-events: none; }
.segment label {
  margin: 0; text-align: center; padding: 9px 8px; border-radius: 2px; cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--ink-55);
  transition: background 0.2s var(--ease), color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.segment input:checked + label { background: var(--paper); color: var(--ink); box-shadow: var(--shadow-sm); }

/* quote result */
.quoteresult { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 18px; }
.quoteresult[hidden] { display: none; }
.quoteline { display: flex; justify-content: space-between; gap: 16px; font-size: 14px; padding: 5px 0; color: var(--ink-70); }
.quoteline span:last-child { font-variant-numeric: tabular-nums; font-weight: 550; color: var(--ink); }
.quotetotal {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: 12px; padding-top: 14px; border-top: 1px solid var(--line);
}
.quotetotal .l { font-size: 14px; font-weight: 600; }
.quotetotal .v { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.quotemeta { font-size: 12.5px; color: var(--ink-55); margin-top: 10px; }

/* estimate disclaimer */
.quote-disclaimer {
  font-size: 12px; line-height: 1.5; color: var(--ink-55);
  background: var(--tint); border: 1px solid var(--tint-2); border-radius: var(--radius);
  padding: 10px 12px; margin: 16px 0;
}

/* ============================================================ SECTIONS */
.sec-head { max-width: 760px; margin-bottom: 44px; }
.sec-head .h-xl { margin-top: 10px; }
.sec-head p { margin-top: 12px; }
.sec-head--center { margin-inline: auto; text-align: center; }
.sec-head--center .eyebrow { justify-content: center; }

/* feature / value grid */
.grid { display: grid; gap: 24px; }
/* Grid children default to min-width:auto, so they refuse to shrink below
   their content and push the page wider on narrow screens. */
.grid > *, .split > *, .steps > *, .statcards > *, .logform-grid > * { min-width: 0; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 26px;
  transition: border-color 0.18s var(--ease);
}
/* flat hover: no shadow, no lift */
.card:hover { border-color: var(--ink-40); }
a.card:hover h3 { color: var(--brand-strong); }
/* Maersk keeps icons inline and unboxed, in the brand colour */
.card__icon {
  width: 30px; height: 30px; display: grid; place-items: center;
  color: var(--brand); margin-bottom: 16px;
}
.card h3 { font-size: 19px; margin-bottom: 8px; transition: color 0.18s; }
.card--link { display: flex; flex-direction: column; }
.card--link .textlink { margin-top: auto; padding-top: 16px; }
.card p { color: var(--ink-70); font-size: 15px; }

/* ---- service card: image, centred title, hairline rule, blue link ----
   One piece of markup drives two layouts. It is a <details> so phones get a
   native, accessible accordion; on wider screens the panel is forced open with
   display:contents, which lets the media be ordered above the summary and
   makes the whole thing read as a plain card. No JavaScript is involved, so
   there is no flash of the wrong state on load. */
.scards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }

.scard {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color 0.18s var(--ease);
}
.scard:hover { border-color: var(--ink-40); }

/* No fixed ratio anywhere an image lives: the box takes the artwork's own
   proportions, so the image always fills it edge to edge with nothing cropped
   and no empty band. The three service artworks share one ratio, so the cards
   still line up with each other. */
.scard__media { background: var(--tile); }
.scard__media img { width: 100%; height: auto; display: block; }

.scard__head {
  list-style: none;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 22px 22px 0;
}
.scard__head::-webkit-details-marker { display: none; }
.scard__head h3 { font-size: 19px; font-weight: 600; letter-spacing: -0.012em; }

.scard__rule { display: block; height: 1px; background: var(--line); margin: 18px 22px 0; }

.scard__link {
  display: flex; align-items: center; justify-content: flex-end; gap: 7px;
  padding: 14px 22px 20px;
  font-size: 14.5px; font-weight: 500; color: var(--brand-strong);
  transition: gap 0.18s var(--ease);
}
.scard:hover .scard__link { gap: 11px; text-decoration: underline; text-underline-offset: 3px; }

/* the plus is the phone affordance only */
.scard__plus { display: none; }

/* ---- tablet and up: always-open card, media above the title ---- */
@media (min-width: 621px) {
  .scard { display: flex; flex-direction: column; }
  /* keeps the panel rendered even when the <details> is closed, in both the
     old (display:none on children) and current (::details-content) engines */
  .scard::details-content { content-visibility: visible; display: contents; }
  .scard__panel { display: contents; }
  .scard__media { order: 1; }
  .scard__head { order: 2; cursor: default; }
  .scard__rule { order: 3; }
  .scard__link { order: 4; margin-top: auto; }   /* links line up across the row */
}

/* ---- phone: the same cards become an accordion ----
   Collapsed by default so the three services preview in one screen, and the
   image only loads its share of attention once a row is opened. */
@media (max-width: 620px) {
  .scards { grid-template-columns: 1fr; gap: 0; border-top: 1px solid var(--line); }
  .scard {
    background: transparent; border: 0; border-bottom: 1px solid var(--line);
    border-radius: 0; overflow: visible;
  }
  .scard:hover { border-color: var(--line); }
  .scard__head {
    justify-content: space-between; gap: 16px;
    padding: 4px 2px; min-height: 56px; cursor: pointer;
  }
  .scard__head h3 { font-size: 17px; font-weight: 600; }

  .scard__plus {
    display: block; position: relative; width: 16px; height: 16px; flex-shrink: 0;
    color: var(--ink-55); transition: transform 0.25s var(--ease), color 0.25s;
  }
  .scard__plus::before, .scard__plus::after {
    content: ''; position: absolute; left: 50%; top: 50%;
    background: currentColor; transform: translate(-50%, -50%);
  }
  .scard__plus::before { width: 16px; height: 2px; }
  .scard__plus::after { width: 2px; height: 16px; }
  .scard[open] .scard__plus { transform: rotate(45deg); color: var(--brand); }

  .scard__panel { padding: 2px 0 18px; animation: scard-open 0.28s var(--ease); }
  .scard__media { border-radius: var(--radius-md); overflow: hidden; }
  .scard__rule { margin: 14px 0 0; }
  .scard__link { justify-content: flex-start; padding: 12px 0 0; }
}
@keyframes scard-open {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

/* ---- service band: alternating artwork and detail ----
   Each service carries a paragraph and its own call to action, which is more
   than a third-width column holds gracefully: the copy runs to different
   lengths and the rows fall out of step with one another. A full-width band
   per service lets every row set its own height and shows the artwork at
   roughly twice the size. Rows alternate so the eye zig-zags down the page
   rather than marching straight down one edge. */
.svcrow {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: stretch;
  padding-block: 64px;
  border-top: 1px solid var(--line);
}
.svcrow:first-of-type { border-top: 0; padding-top: 0; }
.svcrow:last-of-type { padding-bottom: 0; }
.svcrow > * { min-width: 0; }

.svcrow__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--tile);
  align-self: center;
}
.svcrow__media img { width: 100%; height: auto; display: block; }
.svcrow:nth-of-type(even) .svcrow__media { order: 2; }

/* The body spreads over the full height of the row so the heading sits level
   with the top edge of the artwork and the button with its bottom edge. */
.svcrow__body { display: flex; flex-direction: column; justify-content: space-between; }
.svcrow__body .lead { margin-top: 14px; }
.svcrow__cta { margin-top: 30px; display: flex; gap: 12px; flex-wrap: wrap; }

/* ---- carousel controls ----
   Shared by the service bands and the About principles: on narrow screens one
   card shows at a time and these arrows step through the set, wrapping at
   both ends. Hidden by CSS at widths where every card is already visible. */
.carousel-nav { display: none; align-items: center; justify-content: center; gap: 14px; margin-top: 30px; }
.carousel-nav .roundbtn { width: 52px; height: 52px; }
.carousel-nav .roundbtn svg { width: 20px; height: 20px; }

/* variant with a progress line between the arrows */
.carousel-nav--bar { gap: 18px; }
.carousel-nav__bar {
  flex: 1; height: 4px; background: var(--ink-10);
  border-radius: 999px; overflow: hidden;
}
.carousel-nav__bar span {
  display: block; width: 100%; height: 100%; background: var(--ink);
  border-radius: 999px; transform-origin: left;
  transition: transform 0.28s var(--ease);
}

/* In carousel mode the track drops out of whatever grid it was in, so the one
   visible card takes the full width. Above the breakpoint this class does
   nothing and the original grid or stack applies. */
@media (max-width: 860px) {
  .carousel { display: block; }
  .carousel > * { width: 100%; }
}

/* ---- phone and small tablet: one service at a time, artwork first ---- */
@media (max-width: 860px) {
  /* the bar variant belongs to the steps row, which only becomes a scroller
     on phones — see the 620px block */
  .carousel-nav:not(.carousel-nav--bar) { display: flex; }
  .svcrow {
    grid-template-columns: 1fr;
    gap: 18px;
    padding-block: 0;
    border-top: 0;
  }
  .svcrow:nth-of-type(even) .svcrow__media { order: 0; }
  .svcrow__body { display: block; }
  .svcrow__body .lead { margin-top: 10px; }
  .svcrow__cta { margin-top: 22px; }
  .svcrow__cta .btn { flex: 1 1 auto; }
}

/* stat strip */
.statstrip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden; }
.statstrip > div { background: var(--paper); padding: 28px 26px; }
.statstrip .n { font-size: 34px; font-weight: 400; letter-spacing: -0.02em; }
.statstrip .l { font-size: 14px; color: var(--ink-55); margin-top: 4px; }

/* process steps — icon led, joined by a connecting line */
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.step { position: relative; }
/* the icon sits in a soft tinted disc, which gives the row of steps a set of
   anchors for the connector to run between */
.step__icon {
  width: 60px; height: 60px; border-radius: 50%;
  background: var(--tint); color: var(--brand-strong);
  border: 1px solid var(--tint-2);
  display: grid; place-items: center; margin-bottom: 20px;
  position: relative; z-index: 1;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.step:hover .step__icon { background: var(--brand); border-color: var(--brand); color: var(--ink); }
/* hairline connector from each disc to the next, across the grid gap */
.step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 30px;               /* centre of the 60px disc */
  left: 72px;
  right: -24px;
  height: 1px;
  background: var(--line);
}
.step h3 { font-size: 17px; font-weight: 500; margin-bottom: 7px; }
.step p { font-size: 14.5px; color: var(--ink-70); }

/* dark CTA band */
.band { background: var(--ink); color: var(--paper); border-radius: var(--radius-md); padding: 56px 48px; text-align: center; }
.band .h-xl { color: var(--paper); }
.band p { color: rgba(255,255,255,0.8); margin-top: 14px; max-width: 54ch; margin-inline: auto; }
.band .band__cta { margin-top: 26px; display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* split feature — bottom-aligned so the media block ends level with the text column */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: end; }
.split__media {
  aspect-ratio: 4 / 3; border-radius: var(--radius-lg); background: var(--ink);
  position: relative; overflow: hidden;
}
/* THE RULE: a photo panel starts level with the heading beside it and ends
   level with the last thing in that column (usually the buttons). Nothing of
   the panel hangs past the text.

   To get that, the text column has to set the row height. The image is taken
   out of flow (absolute) so its natural height cannot stretch the row, then
   the panel fills the row exactly and the image covers the panel. Previously
   the image was in flow, so a tall artwork pushed the panel below the buttons.

   The artwork is centred, so `cover` trims its background margins rather than
   the illustration. --photo-top/--photo-bottom stay as the panel fill, sampled
   from the artwork's own edge rows, so any letterboxing is invisible. */
.split--photo { align-items: stretch; }
.split__media--photo {
  aspect-ratio: auto;
  background: var(--tile);
  position: relative;
  overflow: hidden;
  min-height: 180px;   /* floor, so a very short column cannot squash it to a line */
}
.split__media--photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* resampled from the green artwork delivered 2026-07-22 */
.split__media--transit { --photo-top: #c7e0e1; --photo-bottom: #ccefe8; }
.split__media--ghchi { --photo-top: #c6e2d7; --photo-bottom: #c8dad8; }

/* Stacked: there is no text column beside it to take the height from, so the
   panel needs its own proportions or it would collapse to the min-height. */
@media (max-width: 1080px) {
  .split__media--photo { aspect-ratio: 4 / 3; min-height: 0; }
}

/* Spec list — hairline-separated rows with a small brand marker. Replaces the
   tick-icon checklist, which read as a feature grid rather than a statement. */
.speclist { margin-top: 28px; border-top: 1px solid var(--line); }
.speclist li {
  list-style: none;
  /* flex-start, not center: on a wrapped item the marker belongs beside the
     first line rather than floating in the middle of the block */
  display: flex; align-items: flex-start; gap: 14px;
  padding: 15px 2px;
  border-bottom: 1px solid var(--line);
  font-size: 16px; line-height: 1.5; color: var(--ink-90);
}
.speclist li::before {
  content: '';
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand); flex-shrink: 0;
  margin-top: 0.55em;   /* optical centre of the first line */
}
ul { padding: 0; margin: 0; }

/* ============================================================= PAGE HERO */
.pagehero { background: var(--ink); color: #fff; }
.pagehero__inner { padding-block: 64px 58px; max-width: 780px; }
.pagehero .eyebrow { color: var(--paper-55); }
.pagehero h1 { color: #fff; margin-top: 14px; }
.pagehero p { color: rgba(255,255,255,0.82); font-size: 17px; margin-top: 16px; max-width: 62ch; }

/* ============================================================== PANEL */
.panel {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 30px;
}
.panel--pad-lg { padding: 40px; }

/* track result / timeline */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 26px 34px; }
.timeline li::before {
  content: ''; position: absolute; left: 8px; top: 20px; bottom: -6px; width: 2px; background: var(--line);
}
.timeline li:last-child::before { display: none; }
.timeline .dot {
  position: absolute; left: 0; top: 4px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--ink-40);
}
.timeline li.is-current .dot { background: var(--ink); border-color: var(--ink); box-shadow: 0 0 0 4px var(--ink-10); }
.timeline .t-status { font-weight: 650; font-size: 16px; }
.timeline .t-note { color: var(--ink-70); font-size: 14px; margin-top: 2px; }
.timeline .t-time { color: var(--ink-55); font-size: 12.5px; margin-top: 3px; }

/* status pill (monochrome tiers — color-code once brand palette is set) */
.pill {
  display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 500;
  padding: 5px 11px; border-radius: 999px; border: 1px solid var(--ink-15); color: var(--ink-70);
  white-space: nowrap; background: #fff;
}
.pill .pdot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-40); }
/* Delivered is the milestone status: the solid dark blue, matching the primary
   button. It reads as the most finished state and stays clearly apart from the
   outlined "Out for Delivery" pill beside it. */
.pill[data-status='Delivered'] {
  background: var(--ink);
  color: #fff; border-color: transparent; font-weight: 600;
}
.pill[data-status='Delivered'] .pdot { background: #fff; }
.pill[data-status='Out for Delivery'] { border-color: var(--ink); color: var(--ink); }
.pill[data-status='Out for Delivery'] .pdot { background: var(--ink); }
.pill[data-status='Shipment Ready'] { border-color: var(--ink); color: var(--ink); }
.pill[data-status='Shipment Ready'] .pdot { background: var(--ink); }
/* On Hold is the one exception state: a subtle red so it reads as "needs
   attention" without shouting next to the calm green palette. */
.pill--hold {
  background: #fdf3f2; color: #9a2f26; border-color: #eecac5; margin-left: 6px;
}
.pill--hold .pdot { background: #c0392b; }

/* payment-status pill: its own tiers, kept visually distinct from shipment
   status. Paid is the settled milestone (solid green); the pre-fee and pending
   states are quiet; Refunded/Waived read as neutral closed states. */
.pill--pay { font-size: 12px; }
.pill--pay[data-pay-status='Paid'] { background: #eef7f1; color: #0f7a52; border-color: #bfe0cd; }
.pill--pay[data-pay-status='Payment Pending'] { background: #fff7ec; color: #8a5a10; border-color: #f0d9ac; }
.pill--pay[data-pay-status='Calculating Fees'] { background: var(--tint); color: var(--ink-70); border-color: var(--tint-2); }
.pill--pay[data-pay-status='Pending Fee Calculation'] { color: var(--ink-55); }
.pill--pay[data-pay-status='Waived'] { background: var(--ink-06); color: var(--ink-70); border-color: var(--ink-15); }
.pill--pay[data-pay-status='Refunded'] { background: var(--ink-06); color: var(--ink-70); border-color: var(--ink-15); }

/* ============================================================== MODAL */
.modal { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 20px; }
.modal[hidden] { display: none; }
.modal__scrim { position: absolute; inset: 0; background: rgba(6,45,40,0.42); }
.modal__panel {
  position: relative; width: min(560px, 100%); max-height: calc(100vh - 40px);
  overflow-y: auto; background: #fff; border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); animation: modalIn 0.22s var(--ease);
}
@keyframes modalIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.modal__head {
  position: sticky; top: 0; background: #fff; z-index: 1;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  padding: 22px 22px 14px; border-bottom: 1px solid var(--line);
}
.modal__head h3 { font-size: 19px; }
.modal__head .sub { font-size: 13px; color: var(--ink-55); margin-top: 3px; }
.modal__body { padding: 18px 22px 24px; }

.paysummary {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px;
  background: var(--tint); border-radius: var(--radius-md); padding: 16px; margin-bottom: 20px;
}
/* align-items: flex-start so the status pill sits at its natural width instead
   of a column-stretched full-width bar. */
.paysummary > div { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; min-width: 0; }
.paysummary .pill { max-width: 100%; }
.paysummary__k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-55); font-weight: 600; }
.paysummary strong { font-size: 18px; }

.paysection { border-top: 1px solid var(--line); padding-top: 16px; margin-top: 16px; }
.paysection:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
.paysection__title { font-weight: 600; font-size: 14px; margin-bottom: 10px; }
.paysection__hint { font-size: 12px; color: var(--ink-55); margin-top: 8px; }
.paysection--hold { display: flex; align-items: center; justify-content: space-between; gap: 14px; }

.payrow { display: flex; gap: 10px; align-items: center; }
.payrow .input, .payrow .select { height: 40px; padding-block: 0; }
.payrow--3 { display: grid; grid-template-columns: 1fr auto auto; }
/* On a phone three controls in a row squeeze the amount to nothing, so drop to
   amount + method on top and a full-width Record button underneath. */
@media (max-width: 560px) {
  .payrow--3 { grid-template-columns: 1fr 1fr; }
  .payrow--3 .btn { grid-column: 1 / -1; }
}
.payrow--wrap { flex-wrap: wrap; }
.payrow .btn { flex-shrink: 0; }
#pay-fill-outstanding { margin-top: 10px; font-size: 13px; }

.feegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.feegrid .field { margin: 0; }

/* exchange rate field: "$1 = [ 12.50 ] GH₵" reads as one unit */
.ratefield { display: inline-flex; align-items: center; gap: 8px; }
.ratefield__pre, .ratefield__post { font-weight: 600; color: var(--ink-70); white-space: nowrap; }
.ratefield .input { width: 130px; height: 40px; padding-block: 0; }

/* styled confirm / prompt dialog */
.modal__panel.confirm { width: min(420px, 100%); }
.confirm__body { padding: 24px 24px 18px; }
.confirm__body h3 { font-size: 18px; margin-bottom: 8px; }
.confirm__body p { font-size: 14px; color: var(--ink-70); line-height: 1.5; }
.confirm__actions {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 24px 22px; border-top: 1px solid var(--line);
}

.payhistory { display: flex; flex-direction: column; gap: 8px; }
.payhistory__row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius); flex-wrap: wrap;
}

/* ============================================================== TOAST */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px);
  z-index: 90; max-width: min(460px, calc(100vw - 32px));
  background: var(--ink); color: #fff; padding: 13px 18px; border-radius: var(--radius-md);
  font-size: 14px; box-shadow: var(--shadow-lg); opacity: 0;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease); text-align: center;
}
.toast.is-in { opacity: 1; transform: translate(-50%, 0); }
/* success in the deep green (brand), error in a clear red */
.toast[data-type='success'] { background: var(--ink); }
.toast[data-type='error'] { background: #9a2f26; }

/* ================================================= TRACK PAYMENT PANEL */
.paypanel {
  border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 18px 20px; margin-bottom: 24px; background: var(--tint);
}
.paypanel--due { border-color: #f0d9ac; background: #fffaf1; }
.paypanel--ok { border-color: var(--tint-2); }
.paypanel__head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 14px; }
.paypanel__label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; color: var(--ink-55); }
.paypanel__msg { font-size: 13.5px; color: var(--ink-70); margin: 0; }
.paypanel__lines { display: flex; flex-direction: column; gap: 8px; font-size: 14px; }
.paypanel__lines > div { display: flex; justify-content: space-between; gap: 12px; color: var(--ink-70); }
.paypanel__total {
  border-top: 1px solid var(--line); margin-top: 4px; padding-top: 10px;
  font-weight: 700; color: var(--ink) !important; font-size: 15px;
}
.paypanel__balance {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  margin: 16px 0; padding-top: 14px; border-top: 1px dashed #e6c98f;
}
.paypanel__balance strong { font-size: 22px; }
.paypanel__disclaimer { font-size: 11.5px; color: var(--ink-55); margin: 14px 0 0; line-height: 1.5; font-style: italic; }
/* keep the four tracking info cells two-up on phones rather than a tall stack */
@media (max-width: 640px) { .track-info { grid-template-columns: 1fr 1fr; } }

/* ============================================================== FAQ */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: 22px 4px; display: flex; justify-content: space-between;
  align-items: center; gap: 24px; font-size: 18px; font-weight: 600;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary .plus { flex-shrink: 0; transition: transform 0.25s var(--ease); color: var(--ink-55); }
.faq details[open] summary .plus { transform: rotate(45deg); }
.faq .faq__a { padding: 0 4px 24px; color: var(--ink-70); max-width: 74ch; }

/* ============================================================== PROSE */
.prose { max-width: 74ch; }
.prose h2 { font-size: 20px; margin-top: 36px; margin-bottom: 10px; }
.prose h2:first-child { margin-top: 0; }
.prose p { color: var(--ink-70); margin-bottom: 12px; }
.prose ul { padding-left: 20px; margin-bottom: 14px; }
.prose li { list-style: disc; color: var(--ink-70); margin-bottom: 6px; }
.prose a { color: var(--brand-strong); text-decoration: underline; text-underline-offset: 3px; }
.prose .updated {
  font-size: 13px; color: var(--ink-55); border-bottom: 1px solid var(--line);
  padding-bottom: 16px; margin-bottom: 28px;
}

/* ============================================================== ALERT */
.alert { border-radius: var(--radius); padding: 13px 15px; font-size: 14px; border: 1px solid var(--ink-40); background: var(--ink-06); }
.alert--error { border-color: var(--ink); background: var(--ink); color: var(--paper); }
.alert[hidden] { display: none; }

/* ============================================================== FOOTER
   Light-blue JB Hunt-style footer: bold black headers, blue links. */
.footer { background: var(--tint); color: var(--ink); padding-block: 56px 26px; margin-top: 0; }
/* Five evenly-weighted columns. The connect column gets a touch more room for
   the social row and blurb without breaking the even rhythm. */
/* Five evenly-weighted columns. The connect column gets a touch more room for
   the social row and blurb without breaking the even rhythm. */
.footer__top { display: grid; grid-template-columns: repeat(4, 1fr) 1.25fr; gap: 40px; padding-bottom: 36px; border-bottom: 1px solid var(--tint-2); align-items: start; }
.footer h4 { font-size: 15px; letter-spacing: 0; text-transform: none; color: var(--ink); margin-bottom: 15px; font-weight: 600; }
/* columns are <details> so they can collapse on mobile; on desktop the summary
   is just a heading and the chevron is hidden */
.footer__col > summary {
  font-size: 15px; font-weight: 600; color: var(--ink); margin-bottom: 15px;
  list-style: none; cursor: default;
}
.footer__col > summary::-webkit-details-marker { display: none; }
.footer__col .chev { display: none; }
.announce__short { display: none; }
.footer__links { display: grid; gap: 11px; }
.footer__links a { color: var(--brand-strong); font-size: 14.5px; transition: color 0.15s; }
.footer__links a:hover { color: var(--brand-strong); text-decoration: underline; text-underline-offset: 3px; }
.footer .brand__type { color: var(--ink); }
.footer__blurb { color: var(--ink-70); font-size: 14px; margin-top: 14px; max-width: 30ch; }
.footer__address { font-style: normal; font-size: 14px; line-height: 1.5; color: var(--ink-70); }
.footer__social { display: flex; gap: 14px; margin-bottom: 20px; }
.footer__social a { color: var(--ink); display: grid; place-items: center; transition: color 0.15s, transform 0.15s; }
.footer__social a:hover { color: var(--brand); }
.footer__tag { font-weight: 800; font-size: 18px; line-height: 1.2; color: var(--brand-deep); letter-spacing: -0.02em; }
.footer__bottom { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-top: 22px; font-size: 13px; color: var(--ink-55); flex-wrap: wrap; }
.footer__bottom .legal { display: flex; gap: 18px; flex-wrap: wrap; }
.footer__bottom a { color: var(--brand-strong); }
.footer__bottom a:hover { color: var(--brand-strong); text-decoration: underline; }

/* ============================================================ UTILITIES */
.mt-0 { margin-top: 0; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.mt-32 { margin-top: 32px; }
.center { text-align: center; }
.stack-sm > * + * { margin-top: 10px; }
.hide-mobile { }
[hidden] { display: none !important; }

.spinner {
  width: 16px; height: 16px; border: 2px solid var(--paper-55); border-top-color: var(--paper);
  border-radius: 50%; animation: spin 0.7s linear infinite; display: inline-block;
}
.spinner--ink { border-color: var(--ink-15); border-top-color: var(--ink); }
@keyframes spin { to { transform: rotate(360deg); } }

/* reveal on scroll */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }

/* ============================================================ DASHBOARD */
.appbar {
  position: sticky; top: 0; z-index: 40; background: var(--ink); color: var(--paper);
  border-bottom: 1px solid var(--paper-15);
}
.appbar__inner { display: flex; align-items: center; gap: 12px; height: 62px; }
/* logo icon links home; the logged-in account name sits where the wordmark was */
.appbar__home { display: inline-flex; align-items: center; flex-shrink: 0; }
.appbar__home .brand__mark { height: 30px; width: auto; }
.appbar__account { display: inline-flex; align-items: center; min-width: 0; overflow: hidden; }
.appbar__name { font-size: 16px; font-weight: 700; color: var(--paper); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.appbar__right { margin-left: auto; display: flex; align-items: center; gap: 12px; }
/* borderless sign-out: label then icon, transparent on the dark bar */
.appbar__signout {
  display: inline-flex; align-items: center; gap: 7px;
  background: transparent; border: 0; color: var(--paper);
  font-family: inherit; font-size: 14px; font-weight: 500; line-height: 1;
  padding: 8px 4px; border-radius: var(--radius); cursor: pointer;
  transition: opacity 0.15s;
}
.appbar__signout:hover { opacity: 0.72; }
.appbar__signout svg { flex-shrink: 0; }

/* Wider working area so the whole table shows at a glance.

   The staff console is a working tool, not a marketing page: the 1320px cap and
   32px marketing gutter left ~190px of dead margin on a 1440 screen while the
   table itself was scrolling sideways. It now runs nearly full width with a
   small gutter, so the space goes to the data.

   The upper cap is kept (very wide) only to stop auto-layout stretching eight
   columns across an ultrawide monitor, which reads as content floating in gaps. */
.appbar .container, .dash > .container {
  max-width: 1800px;
  padding-inline: 16px;
}
@media (min-width: 1600px) {
  .appbar .container, .dash > .container { padding-inline: 24px; }
}
.dash { padding-block: 28px 60px; }
.dash__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 22px; }
/* the heading takes the slack so the action buttons stay grouped on the right */
.dash__head h1 { margin-right: auto; }

/* Compact mode: one button strips the filters, the toolbar and any open editor,
   leaving the highlights and the package table. Height is animated rather than
   display:none so it collapses smoothly instead of snapping. */
.dash-collapsible {
  overflow: hidden;
  max-height: 400px;
  transition: max-height 0.3s var(--ease), opacity 0.2s var(--ease),
              padding 0.3s var(--ease), margin 0.3s var(--ease);
}
/* Padding and border have to go too: max-height alone bottoms out at
   padding + border, which left the filter bar as a 20px sliver. */
.dash.is-compact .dash-collapsible {
  max-height: 0;
  opacity: 0;
  margin-bottom: 0;
  padding-block: 0;
  border-block-width: 0;
  pointer-events: none;
}

.select--sm { padding: 7px 28px 7px 10px; font-size: 13px; background-position: right 10px center; }

/* toolbar: search + actions */
.dash-toolbar { display: flex; gap: 10px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
/* The search field matches the height of the buttons beside it. .btn--sm sets
   its own --btn-h, so read the same value here rather than repeating a number. */
.dash-toolbar .search {
  flex: 1;
  min-width: 240px;
  height: 40px;
  padding-block: 0;
}

/* collapsible "log a package"
   Spacing lives INSIDE the animated area. A margin on .is-open was applied
   instantly and made the table jump before the animation ran. */
.collapse { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s var(--ease); }
.collapse.is-open { grid-template-rows: 1fr; }
.collapse__wrap { overflow: hidden; min-height: 0; }
.collapse__inner {
  border: 1px solid var(--line); border-radius: var(--radius-md); padding: 22px; background: var(--tint);
  margin-bottom: 16px;
}
.logform-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }
.logform-grid .field { margin: 0; }
.logform-actions { display: flex; gap: 10px; align-items: center; margin-top: 16px; flex-wrap: wrap; }

.data-table-wrap { border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden; background: var(--paper); }
.table-scroll { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.data th { text-align: left; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-55); font-weight: 600; padding: 12px 12px; border-bottom: 1px solid var(--line); background: var(--tint); white-space: nowrap; }
/* Top-aligned cells so every row's first line lands on the same baseline. With
   middle alignment, single-line rows floated centred while multi-line rows
   (wrapped name + phone, or status + On Hold) spread out, which read as
   uneven. Top alignment keeps the grid scannable however tall a row gets. */
table.data td { padding: 15px 12px; border-bottom: 1px solid var(--ink-06); vertical-align: top; }

/* Desktop table: let columns size to content (auto layout) so the table stays
   as narrow as the data allows and fits common laptop widths without an inner
   scroll. Scoped to desktop so none of this touches the mobile card grid, which
   reuses the same <td>s with its own placement below 1024px. */
@media (min-width: 1025px) {
  /* keep the flexible Client column from collapsing, and the compact columns
     from ballooning */
  table.data td:nth-child(2) { min-width: 140px; }             /* Client */
  table.data td:nth-child(1), table.data td:nth-child(7) { white-space: nowrap; } /* Tracking, Updated */

  /* Payment column (now 5th): enough room to keep the pill and amount inline */
  table.data td[data-label='Payment'], table.data th:nth-child(5) { min-width: 150px; }

  /* ---- fitting the whole row on screen, no sideways scroll ----
     The table used to run ~1280px wide, which overflowed even a 1440 window and
     badly overflowed a 1280 laptop. Three things were paying for that, and all
     three are recovered without hiding any data:

     1. The status <select> sized itself to its longest option ("Received at
        China Warehouse"), so an invisible string set the width of the widest
        column. It is capped and truncated below. Nothing is lost: the Status
        column beside it already shows the current value in full as a pill, and
        opening the select shows every option at full length.
     2. Cell padding was 12px each side across 8 columns, i.e. ~190px of the
        width was gutters.
     3. The Payment column reserved 190px it did not need. */
  table.data th, table.data td { padding-left: 8px; padding-right: 8px; }
  table.data th:first-child, table.data td:first-child { padding-left: 14px; }
  table.data th:last-child, table.data td:last-child { padding-right: 14px; }
  table.data td { padding-top: 13px; padding-bottom: 13px; }

  .rowactions .select--sm {
    max-width: 132px;
    text-overflow: ellipsis;
  }

  /* Tracking codes are fixed-width and long (ND-072926-670114); a slightly
     smaller mono size keeps the column honest without hurting legibility. */
  table.data td[data-label='Tracking'] .mono { font-size: 12.5px; }
}

/* payment cell (web): pill and amount on one line so the money reads as part of
   the status, not a weak footnote under it. Wraps only if it truly cannot fit. */
/* status pill + On Hold flag flexed in an inner wrapper, NOT on the <td> itself:
   a display:flex td leaves the table model and its bottom border stops lining up
   with the other cells, which broke the row divider at the Status column. */
.statuscell { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; vertical-align: top; }
.statuscell .pill--hold { margin-left: 0; }
/* Status pill leads, amount tucked directly beneath it — a deliberate two-row
   stack instead of a wrap that broke unevenly in the narrow column. */
.paycell { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.paycell__amt { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap; letter-spacing: -0.01em; }
/* the mobile card money line (lives in the Updated cell); web shows the timestamp */
.cardmoney { display: none; }
/* Client name + contact, tight rhythm. These two classes replaced inline
   styles on the row markup, so the type scale lives in one place. */
table.data td[data-label='Client'] { line-height: 1.35; }
table.data td[data-label='Client'] .clcell__who > div:first-child { margin-bottom: 2px; }
.clcell__name  { font-weight: 600; }
.clcell__phone { font-size: 12px; color: var(--ink-55); }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background 0.15s; }
table.data tbody tr:hover { background: var(--tint); }
table.data .col-narrow { white-space: nowrap; }
.mono { font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 12.5px; font-weight: 500; letter-spacing: -0.01em; color: var(--brand-strong); }
.row-flash { animation: flash 1.5s var(--ease); }
@keyframes flash { 0% { background: #cfe8f5; } 100% { background: transparent; } }

.dash-empty { text-align: center; padding: 56px 24px; color: var(--ink-55); }

/* package list pager: prev/next flanking a "X–Y of Z" count */
.pager { display: flex; align-items: center; justify-content: center; gap: 16px; padding: 20px 8px 4px; }
.pager__count { font-size: 13px; font-weight: 500; color: var(--ink-55); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pager .btn[disabled] { opacity: 0.4; cursor: default; pointer-events: none; }

/* team management panel (super admin) */
.stafflist { display: flex; flex-direction: column; gap: 8px; }
.staffrow {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: #fff;
}
.staffrow--off { opacity: 0.55; }
.staffrow__who { flex: 1 1 200px; min-width: 0; }
.staffrow__name { font-weight: 600; font-size: 14px; color: var(--ink); }
.staffrow__email { font-size: 12.5px; color: var(--ink-55); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.staffrow__you {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--brand-strong); background: var(--tint); border-radius: 999px; padding: 1px 7px; margin-left: 6px;
}
.staffrow__role { flex: 0 0 180px; }
.staffrow .rowbtn { flex: 0 0 auto; }
.rowbtn--danger { color: #9a2f26; border-color: #eecac5; }
.rowbtn--danger:hover { background: #fdf3f2; border-color: #9a2f26; }
.rowbtn[disabled] { opacity: 0.4; cursor: default; pointer-events: none; }
.stafform { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.stafform .input { flex: 1 1 180px; }
.stafform .select { flex: 0 0 auto; }

.statcards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 20px; }
.statcards .panel { padding: 18px 20px; }
.statcards .n { font-size: 30px; font-weight: 500; letter-spacing: -0.02em; }
.statcards .l { font-size: 12.5px; color: var(--ink-55); margin-top: 2px; }

/* activity button + count */
/* The count rides inside the button rather than as a badge pinned outside it.
   Hung off the corner it was clipped by the toolbar's overflow, which the
   collapse animation needs, so there is nowhere outside the button to put it. */
.act-btn .count {
  background: var(--ink); color: #fff; font-size: 11px;
  min-width: 18px; height: 18px; border-radius: 9px; display: grid; place-items: center;
  padding: 0 5px; font-weight: 700; margin-inline-start: -2px;
}
.act-btn .count[hidden] { display: none; }

/* activity drawer — subtle, slides in when pulled */
.drawer {
  position: fixed; top: 0; right: 0; height: 100vh; width: min(400px, 92vw); background: #fff;
  border-left: 1px solid var(--line); transform: translateX(100%); transition: transform 0.3s var(--ease);
  z-index: 70; display: flex; flex-direction: column;
}
.drawer.is-open { transform: translateX(0); box-shadow: -24px 0 60px -24px rgba(6, 45, 40, 0.28); }
.drawer__head { padding: 18px 20px; border-bottom: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; }
.drawer__head h3 { font-size: 17px; }
.drawer__head .sub { font-size: 12px; color: var(--ink-55); margin-top: 2px; }
.drawer__close { background: transparent; border: 0; cursor: pointer; color: var(--ink-55); width: 32px; height: 32px; border-radius: var(--radius); display: grid; place-items: center; }
.drawer__close:hover { background: var(--tint); color: var(--ink); }
.drawer__body { overflow-y: auto; flex: 1; }
.drawer__scrim { position: fixed; inset: 0; background: rgba(6, 45, 40, 0.32); opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 65; }
.drawer__scrim.is-open { opacity: 1; pointer-events: auto; }
.act { padding: 13px 20px; border-bottom: 1px solid var(--ink-06); font-size: 13.5px; line-height: 1.45; }
.act:hover { background: var(--tint); }
.act .who { font-weight: 600; }
.act .what { color: var(--ink-70); }
.act .when { color: var(--ink-55); font-size: 12px; margin-top: 3px; display: flex; align-items: center; gap: 7px; }
/* --brand-strong is the token meant for text on white; --brand was failing AA here too */
.act .tag { font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--brand-strong); border: 1px solid var(--tint-2); border-radius: 999px; padding: 1px 7px; }
.act-empty { padding: 40px 20px; text-align: center; color: var(--ink-55); font-size: 13.5px; }

/* ---- dashboard: tablet and below ----
   The table becomes stacked cards so every field stays visible. Nothing is
   hidden and nothing needs sideways scrolling. */
@media (max-width: 1024px) {
  /* Title on its own line, then the two actions side by side sharing the width.
     Left as a flex row they wrapped raggedly: "Hide controls" stayed up beside
     the title and "View public site" dropped to a half-width line of its own. */
  .dash__head { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 10px; }
  .dash__head h1 { grid-column: 1 / -1; margin-right: 0; }
  .dash__head .btn { width: 100%; }
  .dash-filters { gap: 8px 12px; }
  .dash-toolbar .search { min-width: 100%; order: -1; }

  .table-scroll { overflow: visible; }
  table.data { display: block; min-width: 0; }
  table.data thead { display: none; }
  table.data tbody { display: block; }
  /* ---- package card ----------------------------------------------------
     One 2-column grid: content reads down the left edge, values align right.
     Rows in priority order — who+money, state, route, reference, actions.

     Type scale is deliberately three sizes and nothing else:
       15px/600  primary   - client name, money
       13.5px    secondary - destination, measure
       12px      meta      - tracking code, phone, timestamp
     The old caps labels (DESTINATION / PAYMENT / UPDATED) are gone: each cost a
  /* ---- package card (mobile) — matches the approved design -------------
     Two primary lines, each with one pill on the right:
       line 1  client name (700) + phone (400)      | On-Hold flag (only if held)
       line 2  tracking code (700)                  | payment pill
     then a quiet "Last updated" line, a full-width status select, and two
     equal-width buttons. Destination, measure and the money amount are off the
     card face here on purpose — they remain in the desktop table and the
     Edit / Payment views. */
  table.data tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 12px;
    padding: 18px 16px;
    border-bottom: 1px solid var(--line);
    align-items: center;
  }
  table.data tr:last-child { border-bottom: 0; }
  table.data td { display: block; padding: 0; border: 0; min-width: 0; }

  td[data-label='Client']   { grid-column: 1; grid-row: 1; align-self: start; }
  td[data-label='Status']   { grid-column: 2; grid-row: 1; justify-self: end; align-self: start; margin-top: 2px; }
  td[data-label='Tracking'] { grid-column: 1; grid-row: 2; margin-top: 8px; align-self: center; }
  td[data-label='Payment']  { grid-column: 2; grid-row: 2; justify-self: end; align-self: center; margin-top: 8px; }
  td[data-label='Updated']  { grid-column: 1 / -1; grid-row: 3; }
  td[data-label='Actions']  { grid-column: 1 / -1; grid-row: 4; margin-top: 4px; }
  td[data-label='Destination'], td[data-label='Measure'] { display: none; }

  /* line 1: who */
  td[data-label='Client'] .clcell { display: block; }
  .clcell__name  { font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
  .clcell__phone { font-size: 15px; font-weight: 400; color: var(--ink-70); line-height: 1.45; }

  /* line 2: tracking, as bold sans (not the table's mono) to match the design */
  td[data-label='Tracking'] .mono {
    font-family: var(--sans); font-weight: 700; font-size: 17px; color: var(--ink); letter-spacing: 0;
  }

  /* pills: one clean outline style. The status pill is hidden (the select shows
     status); only the On-Hold flag shows on line 1, the payment pill on line 2. */
  td[data-label='Status'] .statuscell { display: block; }
  td[data-label='Status'] .pill[data-status] { display: none; }
  td[data-label='Payment'] .paycell { display: block; }
  /* Size and shape only — colour/border/background come from the semantic pill
     rules (Paid=green, Unpaid=amber, On Hold=red, pre-fee=neutral) so the state
     reads at a glance. Both card pills share one size for a clean rhythm. */
  td[data-label='Status'] .pill--hold,
  td[data-label='Payment'] .pill {
    font-size: 13px; font-weight: 600; padding: 5px 12px; border-radius: 999px;
  }
  td[data-label='Status'] .pill .pdot,
  td[data-label='Payment'] .pill .pdot { display: none; }
  td[data-label='Payment'] .paycell__amt { display: none; }

  /* line 3: the money line — what the client owes, readable without opening the
     package. Replaces the timestamp here (still on the desktop Updated column).
     Prefixed with table.data to outrank `table.data td { display: block }`. */
  table.data td[data-label='Updated'] { display: block; font-size: 14px; }
  td[data-label='Updated'] .upd-time { display: none; }   /* timestamp is web-only */
  td[data-label='Updated'] .cardmoney {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  }
  .cardmoney__lbl { font-size: 13px; font-weight: 500; color: var(--ink-55); }
  .cardmoney__val { font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; white-space: nowrap; }
  /* due amount reads in the same amber as the Unpaid pill; paid stays neutral */
  .cardmoney--due .cardmoney__val { color: #8a5a10; }
  .cardmoney--none .cardmoney__lbl { font-style: italic; }

  /* actions: full-width status select, then two equal buttons — all one height */
  .rowactions { display: flex; flex-wrap: wrap; gap: 10px; }
  .rowactions .select,
  .rowactions .rowbtn,
  .rowactions .locknote { height: 50px; min-height: 50px; font-size: 15px; }
  .rowactions .select { flex: 1 1 100%; max-width: none; font-size: 16px; }
  .rowactions .rowbtn { flex: 1 1 0; min-width: 0; padding-inline: 12px; }
  .rowactions .locknote { flex: 1 1 100%; justify-content: center; }
  .rowactions .rowbtn__ico { display: none; }
  .rowactions .rowbtn__txt { display: inline; }
}

/* ---- dashboard: phone ---- */
@media (max-width: 720px) {
  .statcards { grid-template-columns: repeat(2, 1fr); }
  .appbar__inner { height: auto; padding-block: 10px; gap: 10px; }
  .appbar__right { gap: 10px; }
  .dash-toolbar .btn { flex: 1 1 auto; }
  .logform-actions .btn { flex: 1 1 auto; }
}

/* ---- dashboard: keep the phone view dense and to the point ---- */
@media (max-width: 620px) {
  .dash { padding-block: 16px 36px; }
  .dash__head { margin-bottom: 14px; gap: 10px; }
  .dash__head p { display: none; }   /* explanatory copy, not needed on a phone */
  .dash__head .btn { padding: 8px 12px; font-size: 13px; }
  .statcards { gap: 10px; margin-bottom: 14px; }
  .statcards .panel { padding: 13px 14px; }
  .statcards .n { font-size: 22px; }
  .statcards .l { font-size: 12px; }
  .dash-toolbar { gap: 8px; }
  .collapse__inner { padding: 16px; }
}

@media (max-width: 520px) {
  .statcards { grid-template-columns: 1fr 1fr; gap: 10px; }
  .appbar .brand__mark { height: 24px; }
  .dash-filters { padding: 10px; gap: 8px; }
  /* fixed label column so "Sort by" and "Sort by date" start their controls
     at the same x, instead of each row being pushed by its label width */
  .dash-filters .filter-group {
    flex: 1 1 100%;
    display: grid;
    grid-template-columns: 88px 1fr;
    align-items: center;
    gap: 8px;
  }
  /* The base .dash-filters .input rule is declared later in this file with the
     same specificity, so it would otherwise win and hold the date box at its
     desktop 140px. The extra class here settles the cascade. */
  /* 16px is deliberate: iOS Safari force-zooms the viewport when a focused
     form control is under 16px. The dense desktop bar can stay 12.5px; on a
     phone these must clear the threshold, so tapping Sort never zooms. */
  .dash-filters .filter-group .select,
  .dash-filters .filter-group .input { width: 100%; flex: none; font-size: 16px; min-height: 48px; }
  .dash-filters .filter-reset { margin-left: 0; width: 100%; font-size: 15px; min-height: 44px; }
}

/* ================================================= CONTACT PAGE LAYOUT
   Both columns stretch so the form's bottom edge lines up exactly with the
   bottom of the business-hours card. */
.split--stretch { align-items: stretch; }
.split--stretch > div { display: flex; flex-direction: column; }
/* pinned to the bottom of its column */
.fill-bottom { margin-top: auto; }
.panel-fill { height: 100%; display: flex; flex-direction: column; }
.panel-fill form { display: flex; flex-direction: column; flex: 1; }
.panel-fill .form-end { margin-top: auto; }
/* The message field takes the slack the send button used to sit above: the form
   column is already stretched to match the contact details beside it, so a
   fixed-height textarea left ~150px of dead air in the middle. Growing into it
   balances the panel without changing the row height. */
.panel-fill form .field:has(.textarea) { flex: 1; display: flex; flex-direction: column; }
.panel-fill form .textarea { flex: 1; min-height: 130px; }

/* ------------------------------------------------- dashboard filter bar */
.dash-filters {
  display: flex; gap: 8px 14px; flex-wrap: wrap; align-items: center;
  padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--tint); margin-bottom: 12px;
}
.filter-group { display: flex; align-items: center; gap: 6px; }
.filter-group > label { font-size: 12px; font-weight: 500; color: var(--ink-55); white-space: nowrap; }
.dash-filters .select { padding: 6px 24px 6px 9px; font-size: 12.5px; background-color: #fff; background-position: right 8px center; }
.dash-filters .input { padding: 6px 9px; font-size: 12.5px; background-color: #fff; width: 140px; }
.filter-reset { margin-left: auto; padding: 6px 10px; font-size: 12.5px; }

/* delivered packages are locked for everyone except the master admin */
.locknote {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--ink-55); white-space: nowrap;
}

.rowactions { display: flex; gap: 7px; align-items: center; }
/* Desktop only: fixed-width status select so the Actions column stays compact
   instead of stretching to the longest status name; the value truncates, the
   Status pill already shows it in full. On tablet/mobile the select flexes to
   fill the card (see the max-width:1024px block), so this must not apply there. */
@media (min-width: 1025px) {
  .rowactions .select--sm { width: 152px; flex: none; }
}

/* row action button */
/* Ink, not --brand: the row action sat at 2.5:1 on white, well under the 4.5:1
   AA floor for text this size, and it reads as a button rather than a link. */
.rowbtn {
  background: transparent; border: 1px solid var(--line); border-radius: var(--radius);
  padding: 5px 11px; font-size: 12.5px; font-weight: 600; cursor: pointer; color: var(--ink);
  transition: background 0.15s, border-color 0.15s;
}
.rowbtn:hover { background: var(--tint); border-color: var(--ink); }

/* wider fields inside the log form */
.logform-grid .field--wide { grid-column: 1 / -1; }
.logform-grid .textarea { min-height: 76px; }
.editing-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--brand); border-radius: var(--radius);
  padding: 10px 14px; margin-bottom: 16px; font-size: 13.5px;
}

/* ============================================================ RESPONSIVE */
@media (max-width: 1080px) {
  /* Same reasoning as the phone hero: once the copy runs full width it sits
     above the vessel rather than beside it, so the block needs room underneath
     for the ship to be seen rather than sat on. */
  .hero__inner { padding-block: 56px 220px; max-width: none; }
  .herocard { margin-top: -84px; }
  .split { grid-template-columns: 1fr; gap: 32px; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .statstrip { grid-template-columns: repeat(2, 1fr); }
  /* the connector only makes sense when all four steps sit on one row */
  .step:not(:last-child)::after { display: none; }
}

/* ---- small laptop / landscape tablet (861-1100px) ----
   The full desktop header — brand, five nav links, phone block, CTA and the
   staff-login icon — needs about 1000px and only has 960 at 1024px wide, so it
   was spilling past the viewport. The phone block gives way first: it is the
   least load-bearing of the five, and the number is still in the footer and
   the mobile menu. */
@media (min-width: 861px) and (max-width: 1100px) {
  .contactinfo { display: none; }
  .masthead__inner { gap: 18px; }
  .nav a { padding-inline: 11px; }
}

/* ---- tablet ---- */
@media (max-width: 980px) {
  .footer__top { grid-template-columns: repeat(3, 1fr); gap: 28px; }
}

@media (max-width: 860px) {
  :root { --gutter: 22px; }
  .section { padding-block: 68px; }
  .nav, .contactinfo { display: none; }
  .hamburger { display: flex; }
  .masthead__inner { height: 66px; }

  /* mobile menu */
  .mobilemenu {
    position: fixed; inset: 0 0 0 auto; width: min(330px, 86vw); background: #fff;
    transform: translateX(100%); transition: transform 0.24s var(--ease); z-index: 60;
    display: flex; flex-direction: column; overflow-y: auto;
  }
  .mobilemenu.is-open { transform: translateX(0); box-shadow: -20px 0 50px -25px rgba(6, 45, 40, 0.35); }
  .mobilemenu__head {
    display: flex; justify-content: space-between; align-items: center;
    padding: 13px 16px; border-bottom: 1px solid var(--line);
    position: sticky; top: 0; background: #fff; z-index: 1;
  }
  .menuclose {
    width: 36px; height: 36px; border: 0; background: transparent; border-radius: var(--radius);
    display: grid; place-items: center; color: var(--ink-70); cursor: pointer;
  }
  .menuclose:hover { background: var(--tint); color: var(--ink); }

  .mobilemenu__nav { display: flex; flex-direction: column; }
  .mobilemenu__nav a {
    padding: 16px; font-size: 17px; font-weight: 500; color: var(--ink);
    border-bottom: 1px solid var(--ink-06);
  }
  .mobilemenu__nav a:active { background: var(--tint); }
  .mobilemenu__nav a[aria-current='page'] { color: var(--ink); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }

  .mobilemenu__foot { margin-top: auto; padding: 16px; display: grid; gap: 14px; border-top: 1px solid var(--line); }
  .mobilemenu__sub { display: flex; gap: 18px; font-size: 14px; }
  .mobilemenu__sub a { color: var(--brand); font-weight: 600; }
  .mobilemenu__tel { display: grid; gap: 1px; }
  .mobilemenu__tel span { font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-55); font-weight: 650; }
  .mobilemenu__tel strong { font-size: 15.5px; }

  .scrim { position: fixed; inset: 0; background: rgba(6,45,40,0.45); opacity: 0; pointer-events: none; transition: opacity 0.24s; z-index: 55; }
  .scrim.is-open { opacity: 1; pointer-events: auto; }
}
@media (min-width: 861px) { .mobilemenu, .scrim { display: none; } }

/* ---- phone type scale ----
   Measured off maersk.com at 375px: base body 16/24, small 14/20, lead 18/26,
   H1 38/300, H2 26/300, card headings 20/400, controls 16px. The scale here
   matches that, allowing a little for Inter running wider than Maersk Text.
   The previous scale topped out at 15.5px body and a 28px H1, which was
   noticeably tighter than the site it is modelled on. */
@media (max-width: 620px) {
  body { font-size: 16px; line-height: 1.5; }
  .display { font-size: 36px; font-weight: 300; line-height: 1.06; letter-spacing: -0.022em; }
  .h-xl { font-size: 26px; font-weight: 300; line-height: 1.23; letter-spacing: -0.016em; }
  .h-lg { font-size: 20px; line-height: 1.25; }
  .lead, .hero__sub, .pagehero p { font-size: 17px; line-height: 1.52; }
  .eyebrow { font-size: 12px; letter-spacing: 0.09em; }
  .muted, .herocard__note { font-size: 14px; }

  /* no fade-in on phones: content is there the moment you scroll to it */
  .reveal { opacity: 1; transform: none; transition: none; }

  .grid-3, .grid-4, .grid-2, .field-row { grid-template-columns: 1fr; }

  /* ---- How it works: a swipeable row of cards ----
     Stacked vertically the four steps ran off the screen and read as an
     endless list. Side by side they stay in one view and the shape of the row
     tells you there is more to the right. site.js nudges this once when it
     first scrolls into view, so the gesture is discoverable without a label. */
  .steps {
    grid-auto-flow: column;
    grid-auto-columns: 74%;
    grid-template-columns: none;
    gap: 12px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    padding-inline: var(--gutter);
    margin-inline: calc(var(--gutter) * -1);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .steps::-webkit-scrollbar { display: none; }
  .step {
    scroll-snap-align: start;
    background: var(--tint);
    border: 1px solid var(--tint-2);
    border-radius: var(--radius-lg);
    padding: 22px 20px 24px;
  }
  /* the disc needs to lift off the tinted card it now sits on */
  .step .step__icon { background: var(--paper); border-color: var(--paper); margin-bottom: 16px; }
  .carousel-nav--bar { display: flex; }
  .statstrip { grid-template-columns: 1fr 1fr; }   /* 2x2 reads better than a tall stack */
  .statstrip > div { padding: 18px 16px; }

  .section { padding-block: 44px; }
  .section--tight { padding-block: 30px; }
  .sec-head { margin-bottom: 24px; }
  .pagehero__inner { padding-block: 34px 30px; }
  .band { padding: 30px 20px; }
  .panel, .panel--pad-lg { padding: 20px; }
  .card { padding: 20px; }
  .grid { gap: 14px; }

  /* The ship sits mid-frame and the photo is never cropped vertically here, so
     it lands wherever the middle of the hero is. Deep bottom padding moves the
     copy above it and leaves the vessel and open water clear below the
     buttons, instead of the buttons sitting on top of the subject. */
  /* Generous top padding so the headline sits down in the frame rather than
     clamped under the header; the deep bottom padding still keeps the vessel
     and open water clear below the buttons. */
  /* Anchor the copy and buttons to the BOTTOM of the cover rather than pushing
     them down with a fixed padding. Padding alone can't work here: the hero's
     height varies with the device, so any fixed value leaves a pool of dead
     water under the buttons on taller phones. Flex-end pins the block a fixed
     distance above the cover's bottom edge on every screen. svh (with vh as a
     fallback) keeps it stable while Safari's URL bar shows and hides. */
  .hero {
    display: flex;
    align-items: flex-end;
    min-height: 68vh;
    min-height: 68svh;
  }
  .hero > .container { width: 100%; }
  .hero__inner { padding-block: 36px 46px; max-width: none; }
  .hero h1 { margin-top: 12px; }
  /* The block is pinned to the bottom, so spacing added *below* the headline
     lifts the headline up the frame while the sub-copy and buttons stay low. */
  .hero__sub { margin-top: 48px; }
  .hero__cta { margin-top: 24px; gap: 10px; }
  .hero__cta .btn, .band__cta .btn { flex: 1 1 auto; }

  /* the card sits below the hero instead of overlapping it, so nothing is
     covered and both hero buttons stay reachable */
  .herocard { margin-top: 0; border-radius: 0; box-shadow: none; border-bottom: 1px solid var(--line); }
  /* These tabs used to scroll sideways to fit. On a phone that meant the row
     swallowed any vertical drag that started on it and slid the tabs instead
     of scrolling the page. They now share the width evenly and never scroll,
     so the row is inert to touch except on the tabs themselves. */
  .herocard__tabs { overflow: visible; padding: 0 2px; gap: 0; }
  /* Icon over label rather than beside it. Side by side, the three labels plus
     their icons need more width than a 320px screen has, and dropping the
     icons to make room lost the thing that makes the row scannable. Stacked,
     the widest tab only needs the width of its label. */
  .herocard__tab {
    flex: 1 1 0; min-width: 0;
    flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; padding: 12px 4px 10px; font-size: 13.5px; white-space: nowrap;
  }
  .herocard__tab svg { width: 20px; height: 20px; flex-shrink: 0; }
  .herocard__panel { padding: 18px 18px 0; }
  .herocard__row { flex-direction: column; align-items: stretch; gap: 10px; }
  .herocard__row .btn { width: 100%; }
  .band { padding: 34px 22px; }

  /* Controls at Maersk's mobile sizing: 16px label, 48-52px tall. Nothing
     interactive drops below the 44px tap-target floor. */
  .btn { padding: 14px 22px; min-height: 48px; font-size: 16px; }
  .btn--sm { padding: 12px 16px; min-height: 44px; font-size: 15px; }
  .btn--lg { padding: 16px 26px; min-height: 52px; font-size: 16px; }
  .nav a, .mobilemenu__nav a { min-height: 48px; }
  .rowbtn { min-height: 44px; padding-inline: 18px; }
  .menuclose, .announce__close, .drawer__close { min-width: 44px; min-height: 44px; }

  /* 16px on fields is deliberate: iOS Safari zooms the viewport on focus for
     anything smaller, which throws the whole page off centre. */
  .field { margin-bottom: 14px; }
  /* Stacked, the two-up rows were laying a grid gap on top of each field's own
     margin, so gaps inside a row came out double the gaps between rows and the
     form read as unevenly grouped. Dropping the grid here leaves one rhythm. */
  .field-row { display: block; }
  .field-row > .field { margin-bottom: 14px; }
  .field label { margin-bottom: 6px; font-size: 14px; }
  .input, .select, .textarea { padding: 13px 14px; font-size: 16px; min-height: 48px; }
  .textarea { min-height: 104px; }
  .segment label { padding: 12px 8px; font-size: 15px; }
  .seg-qual { display: none; }        /* "Air Freight" reads fine without ", fast" */
  .field .hint { font-size: 13px; }

  /* Link rows carry their own height so every one clears the 44px tap floor —
     footer columns and card links were landing at 21px and 36px. */
  .footer__links { gap: 2px; }
  .footer__links a,
  .footer__bottom .legal a,
  .mobilemenu__sub a { display: inline-flex; align-items: center; min-height: 44px; }
  .footer__social a { width: 44px; height: 44px; }
  .footer__social { gap: 6px; margin-left: -10px; }
  .footer__bottom .legal { gap: 20px; }
  .scard__link { min-height: 48px; padding-block: 14px 4px; }
  .mobilemenu__tel { min-height: 44px; }
  .masthead .brand { min-height: 44px; }

  .speclist li { font-size: 16px; padding: 16px 2px; }
  .faq summary { font-size: 18px; padding: 20px 2px; }
  .timeline li { padding-left: 32px; }
  .card h3, .step h3, .scard__head h3 { font-size: 20px; }
  .card p, .step p { font-size: 16px; }
  .scard__link, .textlink { font-size: 16px; }
  .statstrip .n { font-size: 24px; }
  .statstrip .l { font-size: 13px; }

  /* footer becomes an accordion so it stays short */
  .footer { padding-block: 34px 22px; }
  .footer__top { grid-template-columns: 1fr; gap: 0; padding-bottom: 20px; }
  .footer__col { border-bottom: 1px solid var(--tint-2); }
  .footer__col > summary {
    display: flex; justify-content: space-between; align-items: center;
    padding: 16px 2px; margin: 0; cursor: pointer; font-size: 16px; min-height: 52px;
  }
  .footer__links a { font-size: 16px; }
  .footer__blurb, .footer__address { font-size: 15px; }
  .footer__bottom { font-size: 14px; }
  .footer__col .chev {
    display: block; width: 9px; height: 9px; flex-shrink: 0;
    border-right: 2px solid var(--ink-55); border-bottom: 2px solid var(--ink-55);
    /* the translate carries the optical offset that margin-top used to, so the
       toggle animates on the compositor instead of reflowing the row */
    transform: translateY(-2px) rotate(45deg);
    transition: transform 0.2s var(--ease);
  }
  .footer__col[open] .chev { transform: translateY(2px) rotate(-135deg); }
  .footer__col > .footer__links { padding: 2px 2px 16px; gap: 13px; }
  .footer__connect { padding-top: 18px; }
  .footer__connect h4 { margin-bottom: 12px; }
}

/* ---- small phones ---- */
@media (max-width: 520px) {
  :root { --gutter: 18px; }
  /* staff login is still reachable from the mobile menu */
  .masthead .iconbtn { display: none; }
  /* At 375px the wordmark, the CTA and the hamburger together ran 47px wider
     than the row, pushing every page into a horizontal scroll. These sizes are
     the largest that fit with room to spare, and the hamburger keeps its full
     44px tap target. */
  .masthead .btn--cta { padding: 10px 12px; font-size: 14px; min-height: 44px; }
  .masthead__inner { height: 62px; gap: 10px; }   /* Maersk's mobile header height */
  .masthead__right { gap: 8px; }
  .brand { gap: 8px; }
  .brand__type { font-size: 16.5px; }
  .brand__mark { height: 26px; }
  .hamburger { width: 44px; height: 44px; }

  /* one compact line instead of three */
  .announce { font-size: 13px; }
  .announce__long { display: none; }
  .announce__short { display: inline; }
  .announce__inner { padding: 7px 36px 7px 0; gap: 6px; text-align: left; justify-content: flex-start; }
  .announce__close { right: 6px; width: 24px; height: 24px; }

  .display { font-size: 32px; }
  .footer__bottom { flex-direction: column; align-items: flex-start; gap: 10px; font-size: 14px; }
}

/* ---- narrowest phones (320-360px) ----
   Below ~370px the wordmark, the CTA and the hamburger cannot share the row
   without overflowing. The CTA is the one to drop: the mobile menu already
   carries "Get Quote" as a full-width button, so the action stays one tap
   away, while the brand name stays visible. */
@media (max-width: 370px) {
  :root { --gutter: 16px; }
  .masthead .btn--cta { display: none; }
  .display { font-size: 30px; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* =====================================================================
   CURRENT RATES card (homepage, directly under the hero card)
   Published air and sea rates. One bordered card holding two priced
   items, split by a hairline rather than made into two separate cards,
   so it reads as a single rate sheet.
   ===================================================================== */
.ratecard {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.ratecard__head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  padding: 24px 26px 20px;
  border-bottom: 1px solid var(--line);
}
.ratecard__eyebrow {
  display: block; margin-bottom: 6px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--brand-strong);
}
.ratecard__updated { font-size: 13px; color: var(--ink-40); white-space: nowrap; }

/* Two equal columns with a single hairline between them. The border sits on
   the second item so it never shows when only one rate is published. */
.ratecard__grid { display: grid; grid-template-columns: 1fr 1fr; }
.ratecard__item { padding: 26px; }
.ratecard__item + .ratecard__item { border-left: 1px solid var(--line); }
.ratecard__item[hidden] { display: none; }

.ratecard__icon { color: var(--brand); margin-bottom: 12px; }
.ratecard__label { font-size: 15px; font-weight: 600; margin-bottom: 6px; }

/* The number is the point of the card, so it gets display scale. Tabular
   figures keep the two prices optically aligned across the columns. */
.ratecard__price {
  font-size: 34px; font-weight: 400; letter-spacing: -0.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.ratecard__unit { font-size: 15px; font-weight: 500; color: var(--ink-70); letter-spacing: 0; }
.ratecard__note { margin-top: 10px; font-size: 14px; color: var(--ink-70); line-height: 1.5; }

.ratecard__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 18px 26px; background: var(--tint); border-top: 1px solid var(--line);
}
.ratecard__disclaimer { font-size: 13px; color: var(--ink-70); line-height: 1.5; margin: 0; }

@media (max-width: 760px) {
  .ratecard__head { flex-direction: column; align-items: flex-start; gap: 6px; padding: 20px; }
  .ratecard__grid { grid-template-columns: 1fr; }
  /* Stacked, the divider has to move from the side to the top. */
  .ratecard__item { padding: 20px; }
  .ratecard__item + .ratecard__item { border-left: 0; border-top: 1px solid var(--line); }
  .ratecard__price { font-size: 28px; }
  .ratecard__foot { flex-direction: column; align-items: stretch; gap: 14px; padding: 20px; }
  .ratecard__foot .btn { width: 100%; }
}

/* =====================================================================
   Floating WhatsApp button (sitewide, dismissible)
   A pill that opens the chat, plus a small round X that removes it.
   Sits above page content but below the mobile menu and any modal.
   ===================================================================== */
.wafab {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  display: flex; align-items: flex-start; gap: 6px;
}

.wafab__btn {
  display: inline-flex; align-items: center; gap: 10px;
  height: 52px; padding: 0 20px 0 16px;
  border-radius: 26px;
  /* WhatsApp brand green. Deliberately not a site token: this button is
     recognised by its colour, and recolouring it to the brand green would
     make it read as just another CTA. */
  background: #25d366; color: #062d28;
  font-size: 15.5px; font-weight: 600; text-decoration: none;
  box-shadow: 0 6px 20px rgba(6, 45, 40, 0.22);
  transition: background-color 0.18s var(--ease);
}
.wafab__btn:hover { background: #1fbb59; }
.wafab__icon { width: 26px; height: 26px; flex: none; }

.wafab__x {
  display: grid; place-items: center;
  width: 26px; height: 26px; flex: none; margin-top: -2px;
  border: 1px solid var(--line); border-radius: 50%;
  background: var(--paper); color: var(--ink-70); cursor: pointer;
  box-shadow: 0 2px 8px rgba(6, 45, 40, 0.16);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.wafab__x svg { width: 14px; height: 14px; }
.wafab__x:hover { color: var(--ink); border-color: var(--ink-40); }

/* On phones the label is dropped to a round icon button: a pill this size
   covers real content on a small screen. The X stays a full 26px so it
   remains an easy tap target next to it. */
@media (max-width: 560px) {
  .wafab { right: 14px; bottom: 14px; }
  .wafab__btn { width: 54px; height: 54px; padding: 0; border-radius: 50%; justify-content: center; }
  .wafab__label { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .wafab__btn, .wafab__x { transition: none; }
}

/* Address links to Google Maps: underline on hover only, so the footer
   address still reads as an address rather than a row of links. */
.footer__maplink { color: inherit; text-decoration: none; }
.footer__maplink:hover { text-decoration: underline; }

/* =====================================================================
   Language switcher (EN / 中文)
   A hairline segmented pair in the masthead, full width in the mobile menu.
   ===================================================================== */
.langsw {
  display: inline-flex; flex: none;
  border: 1px solid var(--line); border-radius: var(--radius-btn);
  overflow: hidden; background: var(--paper);
}
.langsw button {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 0 11px; height: 36px;
  font-family: inherit; font-size: 13.5px; font-weight: 500;
  color: var(--ink-70); white-space: nowrap;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease);
}
.langsw button + button { border-left: 1px solid var(--line); }
.langsw button:hover { color: var(--ink); }
.langsw button.is-on { background: var(--ink); color: var(--paper); }

/* In the mobile menu it sits above the CTA and spans the full width, so both
   options are a comfortable tap target rather than two small pills. */
.langsw--wide { display: flex; width: 100%; margin-bottom: 12px; }
.langsw--wide button { flex: 1; height: 46px; font-size: 15px; }

/* The masthead is tight below ~1080px, where the hotline already hides. The
   switcher goes with it: it is still in the mobile menu, which is what opens
   at that width. */
@media (max-width: 1080px) {
  .masthead .langsw { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .langsw button { transition: none; }
}

/* Address blocks in the footer: office and warehouse listed separately. */
.addrblock + .addrblock { margin-top: 14px; }
.addrblock__label { font-size: 12.5px; font-weight: 600; color: var(--paper); margin-bottom: 4px; }
.addrblock__body { font-style: normal; line-height: 1.55; }
.addrblock__gps { display: block; margin-top: 2px; }

/* Office and warehouse side by side in the hero card, stacking on phones. */
.herocard__row--places { display: flex; gap: 32px; flex-wrap: wrap; }
.herocard__row--places .field { flex: 1 1 240px; }
@media (max-width: 560px) {
  .herocard__row--places { gap: 20px; }
}

/* Row Payment button: emoji on web to keep the table inside the viewport,
   full word on the mobile card layout where width is not the constraint and
   there is no hover to surface a title. */
.rowbtn--icon .rowbtn__ico { display: none; }
@media (min-width: 1025px) {
  .rowbtn--icon { padding-left: 9px; padding-right: 9px; }
  .rowbtn--icon .rowbtn__ico { display: inline; font-size: 15px; line-height: 1; }
  /* Hidden accessibly, not removed: the button keeps its aria-label, and this
     leaves the word available to screen readers reading the button's contents. */
  .rowbtn--icon .rowbtn__txt {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}

/* ---- narrow laptops (1025-1279): the last band before the card layout ----
   The desktop table starts at 1025px, but between there and ~1280 the eight
   columns still could not fit and the row scrolled sideways. Tighten type,
   gutters and the status control across that band so the whole row is visible
   on a 1100px window, which is a normal laptop with a sidebar open.
   No column is dropped: everything stays on screen, just more compactly. */
@media (min-width: 1025px) and (max-width: 1279px) {
  table.data { font-size: 12.5px; }
  table.data th, table.data td { padding-left: 6px; padding-right: 6px; }
  table.data th:first-child, table.data td:first-child { padding-left: 10px; }
  table.data th:last-child, table.data td:last-child { padding-right: 10px; }
  table.data td { padding-top: 11px; padding-bottom: 11px; }
  table.data td[data-label='Tracking'] .mono { font-size: 11.5px; }
  table.data td:nth-child(2) { min-width: 120px; }
  table.data td[data-label='Payment'], table.data th:nth-child(5) { min-width: 128px; }
  .rowactions { gap: 5px; }
  .rowactions .select--sm { max-width: 104px; font-size: 12px; }
  .rowbtn { font-size: 12px; padding-left: 8px; padding-right: 8px; }
  .rowbtn--icon { padding-left: 7px; padding-right: 7px; }
}

/* =====================================================================
   Send-update dialog: pick a drafted SMS, edit, send.
   ===================================================================== */
.modal__panel.smsdlg { width: min(560px, 100%); }

/* Two columns of drafts on desktop so six options fit without a long scroll,
   one column on narrow screens. */
.smsdlg__list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 16px 0 18px; }
@media (max-width: 560px) { .smsdlg__list { grid-template-columns: 1fr; } }

.smsopt {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 10px 12px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--paper); font-family: inherit;
  transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease);
}
.smsopt:hover { border-color: var(--ink-40); }
.smsopt.is-on { border-color: var(--ink); background: var(--tint); }
.smsopt__label { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.smsopt__hint { font-size: 12px; color: var(--ink-55); line-height: 1.35; }

.smsdlg__lbl { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.smsdlg__text { width: 100%; font-size: 13.5px; line-height: 1.5; }
/* Segment count: each SMS is billed per ~160 characters, so going over one
   segment is worth flagging before staff send it. */
.smsdlg__meta { margin-top: 6px; font-size: 12px; color: var(--ink-55); }
.smsdlg__meta .is-warn { color: var(--ink); font-weight: 600; }

@media (prefers-reduced-motion: reduce) { .smsopt { transition: none; } }

/* =====================================================================
   Footer address dropdowns (Office / Warehouse)
   Real collapsibles on every screen size, unlike .footer__col whose
   summary is a static heading on desktop. Built on <details>, so they
   work without JS and are keyboard operable.
   ===================================================================== */
.footer__col--find h4 { margin-bottom: 10px; }

.addrdrop { border-top: 1px solid var(--tint-2); }
.addrdrop:last-child { border-bottom: 1px solid var(--tint-2); }

.addrdrop > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 2px;
  font-size: 14.5px; font-weight: 500; color: var(--brand-strong);
  cursor: pointer; list-style: none;
  transition: color 0.15s var(--ease);
}
.addrdrop > summary::-webkit-details-marker { display: none; }
.addrdrop > summary:hover { color: var(--ink); }
/* Visible keyboard focus: these are the only interactive elements in the
   column and the default outline is clipped by the tight padding. */
.addrdrop > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 2px; }

/* Chevron. The shared .chev is hidden inside .footer__col on desktop, so this
   one is scoped and re-declared rather than inherited. */
.addrdrop .chev {
  display: block; flex: none;
  width: 7px; height: 7px;
  border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.18s var(--ease);
}
.addrdrop[open] .chev { transform: translateY(1px) rotate(-135deg); }

.addrdrop__body {
  display: grid; gap: 4px;
  padding: 0 2px 14px;
  font-style: normal; font-size: 14px; line-height: 1.55; color: var(--ink-70);
}
.addrdrop__meta { font-size: 13px; color: var(--ink-55); }
.addrdrop__map {
  justify-self: start; margin-top: 6px;
  font-size: 13.5px; font-weight: 500; color: var(--brand-strong);
}
.addrdrop__map:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Phones: the whole footer is already an accordion, so give these a taller
   tap target to clear the 44px minimum and sit comfortably among the rest. */
@media (max-width: 720px) {
  .footer__col--find { border-bottom: 1px solid var(--tint-2); padding-bottom: 4px; }
  .addrdrop > summary { padding: 14px 2px; font-size: 15px; }
  .addrdrop__body { padding-bottom: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .addrdrop .chev, .addrdrop > summary { transition: none; }
}

/* ---- mobile shipment cards: stop the row exceeding its wrapper ----
   The card grid is `1fr auto`, and the auto column sized itself to the status
   pill, which does not wrap. With a long status ("Received at China Warehouse")
   the row came out ~19px wider than .data-table-wrap, and since that wrapper is
   overflow:hidden the right edge of every card was being clipped: the pill, the
   timestamp and the action buttons all lost their last few pixels.

   Two fixes, both needed: the flexible column gets an explicit zero floor so it
   can actually shrink (1fr alone keeps a min-content floor), and the pill is
   allowed to wrap so the auto column stops dictating the row width. */
@media (max-width: 1024px) {
  /* Placement lives in the card block above; these two just keep a long status
     or tracking code from forcing the row wider than its wrapper. */
  table.data td[data-label='Status'] .pill { white-space: nowrap; }
  table.data td[data-label='Tracking'] .mono { overflow-wrap: anywhere; }
}

/* ---- staff console on the narrowest phones (<=380px) ----
   At 320px (iPhone SE and older Androids) the app bar's brand plus the user
   block and Sign out button came to more than the available width, pushing the
   whole page into a 41px horizontal scroll. The brand is allowed to truncate
   and the controls tighten; Sign out is never dropped, since it is the only way
   out of the console. */
@media (max-width: 380px) {
  .appbar .container, .dash > .container { padding-inline: 12px; }
  .appbar__inner { gap: 8px; }
  /* The account name yields first — it is decoration here, the console is already
     identified by the page it is on — so it shrinks and truncates while Sign out
     is never dropped (min-width:0 lets a flex item shrink below its content). */
  .appbar__account { flex: 1 1 auto; min-width: 0; overflow: hidden; }
  .appbar__right { gap: 8px; flex: none; }

  /* keep BOTH card pills the same, slightly smaller size on the narrowest phones */
  table.data td[data-label='Status'] .pill--hold,
  table.data td[data-label='Payment'] .pill { font-size: 12.5px; }
}
