/* ============================================================================
* pp-ds.css — the PostPatra design system.
 * ============================================================================
 * This is the single source for type,
spacing,
layout,
surfaces and controls.
 * Anything built after this should use these tokens and classes rather than
 * inventing a value,
because every inconsistency the platform had came from the
 * same habit: a colour or size chosen once,
in one file,
for one screen.
 *
 * WHAT THIS REPLACES
 * Twelve different font sizes in common use with no heading scale. Buttons
 * defined three times with different colours. Two light-theme remap layers
 * patching over hardcoded values. Those are gone; this is what stands in their
 * place.
 *
 * HOW IT APPLIES WITHOUT REWRITING 33 MODULES
 * The baseline is set on ELEMENTS inside .content-wrapper,
for one screen.
 *
 * WHAT THIS REPLACES
 * Twelve different font sizes in common use with no heading scale. Buttons
 * defined three times with different colours. Two light-theme remap layers
 * patching over hardcoded values. Those are gone; this is what stands in their
 * place.
 *
 * HOW IT APPLIES WITHOUT REWRITING 33 MODULES
 * The baseline is set on ELEMENTS inside .pp-scope,
at low specificity.
 * A module that has deliberately styled something still wins. A module that
 * never said anything now inherits a considered default instead of the browser's.
 *
 * THE AUDIENCE SHAPES THE CHOICES
 * Warehouse staff,
often new,
on a wall-mounted touchscreen and on phones. So:
 * controls are 44px minimum,
colour states what an action does,
type is sized
 * for a metre away rather than for a designer's monitor,
and nothing important
 * is communicated by colour alone.
 * ========================================================================== */

/* ---------------------------------------------------------------- 1. TYPE */
:root {
  /* One family for the whole platform. Inter is drawn for interfaces: it keeps
     digits, capital I and lowercase l distinct, which matters when the screen is
     mostly order numbers and tracking codes. system-ui follows so the page is
     readable instantly if the webfont is slow or blocked. */
  --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Eight steps, and no value between them. Every size in the platform maps to
     one of these — that is what makes screens look related. */
  --fs-2xs:   11px;   /* badge, table meta, timestamp        */
  --fs-xs:    12px;   /* caption, helper text                */
  --fs-sm:    13px;   /* dense table cell, secondary label   */
  --fs-base: 14.5px;  /* body — the default for reading      */
  --fs-md:    16px;   /* card title, emphasised body         */
  --fs-lg:    19px;   /* h3 · a group of fields              */
  --fs-xl:    23px;   /* h2 · a section of a page            */
  --fs-2xl:   28px;   /* h1 · the page itself                */

  --lh-tight: 1.25;   /* headings            */
  --lh:       1.55;   /* body                */
  --lh-snug:  1.4;    /* controls and chips  */

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semi:   600;
  --fw-bold:   700;

  --track-caps: 0.08em;   /* uppercase labels need air to stay legible */

  /* ------------------------------------------------------------ 2. SPACE */
  /* A 4px rhythm. Using a step instead of an arbitrary number is what keeps
     gaps between unrelated screens feeling the same. */
  --sp-1:  4px;   --sp-2:  8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px;   --sp-6: 24px;   --sp-8: 32px;  --sp-10: 40px;
  --sp-12: 48px;  --sp-16: 64px;

  /* ----------------------------------------------------------- 3. SHAPE */
  --r-sm:  6px;   --r: 9px;   --r-lg: 14px;   --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.18);
  --shadow:    0 4px 14px rgba(0,0,0,.22);
  --shadow-lg: 0 18px 44px rgba(0,0,0,.34);

  /* ---------------------------------------------------------- 4. LAYOUT */
  --page-max:    1440px;  /* modules fill the work area; this is the outer cap */
  --reading-max:   72ch;  /* prose only — long lines are hard to track        */
  --page-pad:   var(--sp-6);

  /* --------------------------------------------------------- 5. CONTROL */
  --ctl-h:       44px;    /* touch floor — see the note at the top */
  --ctl-h-sm:    36px;    /* dense tables only, never a primary action */
  --ctl-pad-x:   18px;
  --ctl-radius:  var(--r);
  --ctl-gap:     10px;
  --ctl-font:    var(--fs-base);
  --ctl-weight:  var(--fw-semi);

  /* --------------------------------------------------------- 6. INTENT */
  /* Colour states what an action does. One primary per screen. */
  --i-primary:      #2563eb;  --i-primary-ink:  #ffffff;  --i-primary-edge: #1d4ed8;
  --i-confirm:      #047857;  --i-confirm-ink:  #ffffff;  --i-confirm-edge: #065f46;
  --i-danger:       #dc2626;  --i-danger-ink:   #ffffff;  --i-danger-edge:  #b91c1c;
  --i-caution:      #f59e0b;  --i-caution-ink:  #1e1b10;  --i-caution-edge: #d97706;
  --i-info:         #0369a1;  --i-info-ink:     #ffffff;  --i-info-edge:    #075985;
  --i-neutral:      #1e293b;  --i-neutral-ink:  #f8fafc;  --i-neutral-edge: #334155;

  --i-confirm-soft: rgba(16, 185, 129, 0.14);  --i-danger-soft:  rgba(239, 68, 68, 0.14);
  --i-caution-soft: rgba(245, 158, 11, 0.14);  --i-info-soft:    rgba(14, 165, 233, 0.14);
}
:root[data-theme="light"] {
  --i-primary:      #2563eb;  --i-primary-ink:  #ffffff;  --i-primary-edge: #1d4ed8;
  --i-confirm:      #047857;  --i-confirm-ink:  #ffffff;  --i-confirm-edge: #065f46;
  --i-danger:       #dc2626;  --i-danger-ink:   #ffffff;  --i-danger-edge:  #b91c1c;
  --i-caution:      #b45309;  --i-caution-ink:  #ffffff;  --i-caution-edge: #92400e;
  --i-info:         #0369a1;  --i-info-ink:     #ffffff;  --i-info-edge:    #075985;
  --i-neutral:      #f1f5f9;  --i-neutral-ink:  #0f172a;  --i-neutral-edge: #cbd5e1;

  --i-confirm-soft: #ecfdf5;  --i-danger-soft:  #fef2f2;
  --i-caution-soft: #fffbeb;  --i-info-soft:    #f0f9ff;

  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05);
  --shadow:    0 4px 14px rgba(15, 23, 42, 0.07);
  --shadow-lg: 0 18px 44px rgba(15, 23, 42, 0.12);
}
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]):not([data-theme="light"]) {
    --i-primary:      #2563eb;  --i-primary-ink:  #ffffff;  --i-primary-edge: #1d4ed8;
    --i-confirm:      #047857;  --i-confirm-ink:  #ffffff;  --i-confirm-edge: #065f46;
    --i-danger:       #dc2626;  --i-danger-ink:   #ffffff;  --i-danger-edge:  #b91c1c;
    --i-caution:      #b45309;  --i-caution-ink:  #ffffff;  --i-caution-edge: #92400e;
    --i-info:         #0369a1;  --i-info-ink:     #ffffff;  --i-info-edge:    #075985;
    --i-neutral:      #f1f5f9;  --i-neutral-ink:  #0f172a;  --i-neutral-edge: #cbd5e1;
    --i-confirm-soft: #ecfdf5;  --i-danger-soft:  #fef2f2;
    --i-caution-soft: #fffbeb;  --i-info-soft:    #f0f9ff;
  }
}
/* Fluid type. A wall-mounted screen is read from further away than a laptop,
so
   the base grows on large displays instead of staying pinned to 14.5px. */
@media (min-width: 1600px) {
:root { --fs-base: 15.5px; --fs-md: 17px; --fs-lg: 21px; --fs-xl: 26px; --fs-2xl: 32px; }
}
@media (max-width: 560px) {
:root { --fs-2xl: 24px; --fs-xl: 20px; --fs-lg: 17px; --page-pad: var(--sp-4); }
}
/* =================================================== 7. ELEMENT BASELINE
   Low specificity on purpose: this is the floor, not an override. A module that
   has deliberately styled something keeps its styling; a module that never said
   anything now inherits a considered default instead of the browser's.

   :is(.content-wrapper, .pp-scope) covers both kinds of page — modules rendered
   inside dashboard.php, and the standalone help desk screens that have their
   own <html> and carry .pp-scope on the body. */

body,
:is(.content-wrapper, .pp-scope) { font-family: var(--font); }

:is(.content-wrapper, .pp-scope) {
  font-size: var(--fs-base);
  line-height: var(--lh);
}

:is(.content-wrapper, .pp-scope) :is(h1, h2, h3, h4) {
  line-height: var(--lh-tight);
  font-weight: var(--fw-semi);
  text-wrap: balance;
  margin: 0 0 var(--sp-3);
}
:is(.content-wrapper, .pp-scope) h1 { font-size: var(--fs-2xl); letter-spacing: -0.02em; }
:is(.content-wrapper, .pp-scope) h2 { font-size: var(--fs-xl);  letter-spacing: -0.01em; }
:is(.content-wrapper, .pp-scope) h3 { font-size: var(--fs-lg); }
:is(.content-wrapper, .pp-scope) h4 { font-size: var(--fs-md); font-weight: var(--fw-bold); }

:is(.content-wrapper, .pp-scope) p     { margin: 0 0 var(--sp-3); }
:is(.content-wrapper, .pp-scope) small { font-size: var(--fs-xs); }
:is(.content-wrapper, .pp-scope) :is(code, pre) { font-family: var(--font-mono); font-size: 0.9em; }

/* Numbers that sit in a column line up. */
:is(.content-wrapper, .pp-scope) :is(td, th), .pp-num { font-variant-numeric: tabular-nums; }

:is(.content-wrapper, .pp-scope) label, .pp-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  line-height: var(--lh-snug);
}
.pp-eyebrow {
  font-size: var(--fs-2xs); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: var(--track-caps);
}

/* ============================================================ 8. LAYOUT */
.pp-page    { width: 100%; max-width: var(--page-max); margin: 0 auto; padding-bottom: var(--sp-12); }
.pp-prose   { max-width: var(--reading-max); }
.pp-stack   { display: flex; flex-direction: column; gap: var(--sp-4); }
.pp-row     { display: flex; align-items: center; gap: var(--ctl-gap); flex-wrap: wrap; }
.pp-spread  { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.pp-section { margin-bottom: var(--sp-8); }

/* The column count follows the available space, so nothing is stretched across
   dead width or left alone on a row of its own. */
.pp-grid       { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.pp-grid--wide { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }

.pp-head     { margin-bottom: var(--sp-6); }
.pp-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.pp-head h1  { margin-bottom: var(--sp-1); }
.pp-head p   { margin: 0; font-size: var(--fs-sm); }

/* =========================================================== 9. SURFACES */
.pp-card      { border-radius: var(--r-lg); padding: var(--sp-5); border: 1px solid; }
.pp-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.pp-card-head :is(h2, h3) { margin: 0; }
/* Not everything is a card. A well groups things *inside* one. */
.pp-well      { border-radius: var(--r); padding: var(--sp-4); }

/* ============================================================ 10. TABLES */
.pp-table-wrap { overflow-x: auto; border-radius: var(--r); }
:is(.content-wrapper, .pp-scope) table { border-collapse: collapse; width: 100%; }
:is(.content-wrapper, .pp-scope) th {
  text-align: left; font-size: var(--fs-2xs); font-weight: var(--fw-semi);
  text-transform: uppercase; letter-spacing: var(--track-caps);
  padding: var(--sp-3) var(--sp-4); white-space: nowrap;
}
:is(.content-wrapper, .pp-scope) td { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-sm); }

/* =========================================================== 11. BUTTONS
   Colour carries meaning:
     primary  the main action        confirm  completes or dispatches
     danger   destroys something     caution  reversible, worth a look
     info     opens or exports       neutral  backs out, changes nothing
   One primary per screen. Two primaries mean neither reads as the obvious one. */

.pp-a,
:is(.content-wrapper, .pp-scope) :is(.btn, .btn-small),
.filter-actions-top .btn-small,
.helpdesk-filters :is(.btn, .btn-secondary) {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  min-height: var(--ctl-h);
  padding: 0 var(--ctl-pad-x);
  border-radius: var(--ctl-radius);
  border: 1px solid transparent;
  font-family: var(--font);
  font-size: var(--ctl-font);
  font-weight: var(--ctl-weight);
  line-height: var(--lh-snug);
  cursor: pointer; text-decoration: none; max-width: 100%;
  transition: filter .15s ease, background .15s ease, border-color .15s ease;
}

/* Icons take the button's own text colour, so an icon can never disappear
   against the fill it sits on. */
.pp-a svg,
:is(.content-wrapper, .pp-scope) :is(.btn, .btn-small) svg,
.filter-actions-top .btn-small svg { stroke: currentColor; fill: none; flex: none; }

.pp-a:hover,
:is(.content-wrapper, .pp-scope) :is(.btn, .btn-small):hover { filter: brightness(1.08); }
.pp-a:active,
:is(.content-wrapper, .pp-scope) .btn:active { filter: brightness(0.94); }

.pp-a:focus-visible,
:is(.content-wrapper, .pp-scope) :is(.btn, .btn-small, a):focus-visible {
  outline: 3px solid var(--i-info); outline-offset: 2px; border-radius: var(--r-sm);
}

.pp-a[disabled], .pp-a.is-disabled,
:is(.content-wrapper, .pp-scope) :is(.btn, .btn-small)[disabled] {
  opacity: .5; cursor: not-allowed; filter: none;
}

.pp-a--primary,
:is(.content-wrapper, .pp-scope) .btn:not([class*="btn-"]),
:is(.content-wrapper, .pp-scope) .btn-primary {
  background: var(--i-primary); color: var(--i-primary-ink); border-color: var(--i-primary-edge);
}
.pp-a--confirm, :is(.content-wrapper, .pp-scope) .btn-success {
  background: var(--i-confirm); color: var(--i-confirm-ink); border-color: var(--i-confirm-edge);
}
.pp-a--danger, :is(.content-wrapper, .pp-scope) :is(.btn-danger, .btn-delete) {
  background: var(--i-danger); color: var(--i-danger-ink); border-color: var(--i-danger-edge);
}
.pp-a--caution, :is(.content-wrapper, .pp-scope) .btn-warning {
  background: var(--i-caution); color: var(--i-caution-ink); border-color: var(--i-caution-edge);
}
.pp-a--info, :is(.content-wrapper, .pp-scope) .btn-info {
  background: var(--i-info); color: var(--i-info-ink); border-color: var(--i-info-edge);
}
/* Neutral keeps a visible edge: its fill is close to the page, and without a
   border it stops reading as a button at all. */
.pp-a--neutral, :is(.content-wrapper, .pp-scope) :is(.btn-secondary, .btn-cancel) {
  background: var(--i-neutral); color: var(--i-neutral-ink); border-color: var(--i-neutral-edge);
}

.pp-a--sm, :is(.content-wrapper, .pp-scope) .btn-small {
  min-height: var(--ctl-h-sm); padding: 0 13px; font-size: var(--fs-sm);
}
.pp-a--icon  { min-width: var(--ctl-h); padding: 0 10px; }
.pp-a--block { width: 100%; }

/* ============================================================= 12. CHIPS
   A status must never rely on colour alone — colour-blind staff and a sunlit
   screen both defeat it. Pair the chip with a word or an icon. */
.pp-tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 650; line-height: var(--lh-snug);
  border: 1px solid transparent; white-space: nowrap;
}
.pp-tag--confirm { background: var(--i-confirm-soft); color: var(--i-confirm); border-color: var(--i-confirm); }
.pp-tag--danger  { background: var(--i-danger-soft);  color: var(--i-danger);  border-color: var(--i-danger); }
.pp-tag--caution { background: var(--i-caution-soft); color: var(--i-caution); border-color: var(--i-caution); }
.pp-tag--info    { background: var(--i-info-soft);    color: var(--i-info);    border-color: var(--i-info); }

/* ============================================================= 13. FORMS */
:is(.content-wrapper, .pp-scope) :is(
  input[type="text"], input[type="search"], input[type="email"], input[type="number"],
  input[type="date"], input[type="tel"], input[type="password"], select, textarea) {
  min-height: var(--ctl-h);
  border-radius: var(--ctl-radius);
  font-family: var(--font);
  font-size: var(--ctl-font);
  padding: 0 var(--sp-3);
  max-width: 100%;
  box-sizing: border-box;
}
/* :not([rows="1"]) lifts this to the same specificity as the control rule above
   (which matches textarea through :is(input[type], …)) so multi-line boxes stay tall. */
:is(.content-wrapper, .pp-scope) textarea:not([rows="1"]) { min-height: 96px; padding: var(--sp-3); line-height: var(--lh); }
:is(.content-wrapper, .pp-scope) :is(input, select, textarea):focus-visible {
  outline: 3px solid var(--i-info); outline-offset: 1px;
}
.pp-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--sp-4); }
.pp-hint  { font-size: var(--fs-xs); }

/* ============================================================ 14. DIALOGS
   Every dialog needs a visible way out. A dialog you can only leave by guessing
   is the fastest way to make somebody distrust the whole screen. */
.pp-scrim  { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 1400; }
.pp-dialog { border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
             width: min(640px, 94vw); max-height: 90vh; overflow: auto; }
.pp-dialog-head { display: flex; align-items: flex-start; justify-content: space-between;
                  gap: var(--sp-3); padding: var(--sp-5); }
.pp-dialog-body { padding: 0 var(--sp-5) var(--sp-5); }
.pp-dialog-foot { display: flex; gap: var(--sp-2); padding: var(--sp-4) var(--sp-5); flex-wrap: wrap; }
.pp-dialog-close { min-width: var(--ctl-h); min-height: var(--ctl-h); border-radius: var(--r);
                   display: inline-flex; align-items: center; justify-content: center;
                   background: transparent; border: 1px solid transparent; cursor: pointer; }

/* ============================================================ 15. SIGN OUT */
.btn-logout {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 40px; padding: 0 14px;
  background: var(--i-neutral) !important;
  color: var(--i-neutral-ink) !important;
  border: 1px solid var(--i-neutral-edge) !important;
  border-radius: var(--ctl-radius);
}
.btn-logout:hover { filter: brightness(1.08); }

/* ==================================================== 16. RESPONSIVENESS */
@media (max-width: 820px) {
  /* A flex or grid child defaults to min-width:auto, refuses to shrink, and
     widens the whole row. This is the single most common cause of a page that
     scrolls sideways on a phone. Low specificity so an intentional min-width
     still wins. */
  :is(.content-wrapper, .pp-scope) * { min-width: 0; }

  :is(.content-wrapper, .pp-scope) table:not([data-pp-wrapped]) {
    display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
  }
  :is(.content-wrapper, .pp-scope) pre,
  .pp-scroll-x, .pp-table-wrap { overflow-x: auto; max-width: 100%; }

  :is(.content-wrapper, .pp-scope) :is(img, canvas, svg, iframe) { max-width: 100%; height: auto; }

  .pp-head-row, .pp-row, .pp-spread { flex-wrap: wrap; }
  .pp-card { padding: var(--sp-4); }
}

@media (max-width: 560px) {
  .pp-grid, .pp-grid--wide { grid-template-columns: 1fr; }
  /* One full-width control is easier to hit than a row of small ones. */
  :is(.content-wrapper, .pp-scope) .btn, .pp-a { width: 100%; }
  .pp-row > :is(.btn, .pp-a) { flex: 1 1 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, .pp-a, :is(.content-wrapper, .pp-scope) :is(.btn, .btn-small) {
    transition: none !important; animation: none !important;
  }
}

/* Printing a label sheet or a manifest should not print the furniture. */
@media print {
  .sidebar, .bottom-nav, .filter-actions-top, .pp-a, .btn { display: none !important; }
  .content-wrapper { padding: 0; }
}
