/* ══════════════════════════════════════════════════════════════════
   BRAND TYPE — Hub Group
   ──────────────────────────────────────────────────────────────────
   Loaded LAST on purpose. Every other stylesheet in this app sets
   fonts at various specificities and several were written before the
   tokens existed; loading here means the brand faces win without
   having to hunt down each rule.

     Good Headline Pro   all major headlines, ALL CAPS
                         fallback: Franklin Gothic Demi
     IBM Plex Sans       subheads and body
                         fallback: Verdana
     IBM Plex Mono       money, dates, IDs — tabular figures

   Good Headline Pro is licensed and cannot be served from a CDN.
   Drop these four files into static_nlp/fonts/ and the @font-face
   block below picks them up with no other change:

     GoodHeadlinePro-Regular.woff2
     GoodHeadlinePro-Medium.woff2
     GoodHeadlinePro-Bold.woff2
     GoodHeadlinePro-Black.woff2

   Until they exist the browser skips the @font-face silently and
   falls through to Franklin Gothic Demi, which is the substitute the
   guidelines name and is already present on Windows.
   ══════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'Good Headline Pro';
  src: url('/nlp-static/fonts/GoodHeadlinePro-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Good Headline Pro';
  src: url('/nlp-static/fonts/GoodHeadlinePro-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Good Headline Pro';
  src: url('/nlp-static/fonts/GoodHeadlinePro-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Good Headline Pro';
  src: url('/nlp-static/fonts/GoodHeadlinePro-Black.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* ── body ─────────────────────────────────────────────────────────
   Verdana is noticeably wider than IBM Plex Sans, so if the webfont
   fails the page reflows rather than just changing shape. That is the
   trade the guidelines ask for; the sizes below are set in rem so the
   fallback stays readable.
   ─────────────────────────────────────────────────────────────── */
body,
button,
input,
select,
textarea {
  font-family: var(--font-sans);
}

body {
  font-feature-settings: 'cv05' 1, 'ss01' 1;
}

/* ── headlines: display face, caps ────────────────────────────────
   Caps need looser tracking to stay legible, and the display face is
   deliberately NOT applied below ~11px — Good Headline Pro is drawn
   for headline sizes and turns muddy in small caps runs.
   ─────────────────────────────────────────────────────────────── */
h1,
h2,
h3,
h4,
.page-title,
.section-title,
.card-title,
.panel-title,
.modal-title,
.tab-btn,
.rpa-stat-label,
.rpa-stat .label,
.stat-label,
.aw-db-stat-label,
.aw-db-branch-title,
.aw-db-section-title,
.drawer-title,
.cf-title,
.fsum-title,
.fuel-card-title,
.brand-display {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.045em;
  font-weight: 600;
}

h1,
.page-title {
  letter-spacing: 0.05em;
}

/* Sentence-case exceptions — these read as content, not as chrome, and
   shouting them hurts scanning. */
.rule-summary-text,
.rule-sentence,
.toast-message,
.cf-rule-name,
.load-card-lane,
p,
li {
  text-transform: none;
}

/* ── table headers ────────────────────────────────────────────── */
.rules-table thead th,
.rpa-table thead th,
.data-table thead th,
.lm-table thead th,
.fuel-table thead th,
.shp-table thead th,
.aw-db-table thead th {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 600;
}

/* ── field labels ─────────────────────────────────────────────── */
label,
.form-label,
.field-label,
.filter-label {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

/* ── figures: tabular, so money lines up in columns ───────────────
   This is the whole reason for IBM Plex Mono over the previous
   JetBrains Mono — same job, same family as the body face.
   ─────────────────────────────────────────────────────────────── */
.num,
.money,
.rate-value,
.metric-value,
.rpa-stat-value,
.rpa-stat .value,
.stat-value,
.aw-db-stat-value,
.sug-summary-val,
.kpi-val,
td.numeric,
td.r,
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* Any table cell holding a currency or percentage figure. Applied by
   class so the markup stays in control of what counts as a figure. */
.figure-cell {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ── rule lifecycle chips ─────────────────────────────────────────
   Derived on render from effective_from / effective_to / active — see
   getRuleLifecycle() in app.js. Colour is a second signal here, never
   the only one: each chip also carries its word.
   ─────────────────────────────────────────────────────────────── */
.rule-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  align-self: flex-start;
  font-family: var(--font-display);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}

.rule-status::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}

.rule-status-live      { background: var(--pos-soft);  color: var(--pos);  border-color: var(--pos-border); }
.rule-status-scheduled { background: var(--note-soft); color: var(--note); border-color: var(--note-border); }
.rule-status-expiring  { background: var(--warn-soft); color: var(--warn); border-color: var(--warn-border); }
.rule-status-expired,
.rule-status-paused    { background: var(--surface-2); color: var(--ink-3); border-color: var(--border-strong); }

/* Live is the only state with a pulse — it is the one that means
   "this is affecting prices right now". */
.rule-status-live::before { animation: ipe-status-pulse 2.4s ease-in-out infinite; }

@keyframes ipe-status-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--pos-border); }
  50%      { box-shadow: 0 0 0 3px transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .rule-status-live::before { animation: none; }
}