/* ==========================================================================
   CrewByte — foundation layer
   Shared by crewbyte.io, app.crewbyte.io and console.app.crewbyte.io.

   Design position: this is a tool that lives on a greasy phone in a hot
   kitchen. It borrows from industrial signage and instrument panels, not from
   consumer SaaS. That means: hairline rules instead of soft shadows, small
   radii, high contrast, uppercase micro-labels, and tabular numerals so a
   column of temperatures reads like a column of temperatures.
   ========================================================================== */

/* --------------------------------------------------------------- tokens */
:root {
  /* Ink — near-black through to soft grey. Slightly blue-cool to sit against
     the warm paper without looking muddy. */
  --ink-900: #0F1115;
  --ink-800: #171A20;
  --ink-700: #1F242C;
  --ink-600: #2B313B;
  --ink-500: #3D4552;
  --ink-400: #575F6D;
  --ink-300: #767E8C;
  --ink-200: #9AA1AC;

  /* Paper — warm off-white. Pure #FFF is reserved for raised surfaces. */
  --paper:      #F8F7F4;
  --paper-raised: #FFFFFF;
  --paper-sunk: #F1EFE9;
  --paper-deep: #E9E6DE;

  /* Hairlines do the structural work here. */
  --line:        #E3DFD6;
  --line-strong: #CDC7B9;
  --line-dark:   #262C36;
  --line-dark-strong: #333B47;

  /* Accent — deep teal. Confident, clinical, reads as "verified". */
  --accent:      #12876F;
  --accent-deep: #0D6A57;
  --accent-dark: #0A5546;
  --accent-tint: #E3EFEB;
  --accent-tint-strong: #C7DFD8;
  --accent-on-dark: #35B79A;

  /* Signal colours. Amber = attention, red = failure, blue = information. */
  --warn:      #A96C12;
  --warn-tint: #F8EEDC;
  --warn-on-dark: #E2A33F;

  --bad:      #B23A2C;
  --bad-tint: #F8E6E3;
  --bad-on-dark: #E4685A;

  --info:      #2C5A82;
  --info-tint: #E4EDF5;
  --info-on-dark: #6BA3D0;

  --ok:      var(--accent);
  --ok-tint: var(--accent-tint);

  /* Type */
  --font-sans: "Geist", "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", "Cascadia Mono",
               "Roboto Mono", Consolas, monospace;

  /* Spacing — 4px base, named so layout intent survives edits. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px; --s8: 40px;
  --s9: 56px; --s10: 72px; --s11: 96px; --s12: 128px;

  /* Radii — deliberately tight. Nothing here is a pill except status chips. */
  --r-xs: 3px;
  --r-sm: 5px;
  --r-md: 8px;
  --r-lg: 12px;

  --shadow-sheet: 0 -8px 32px rgba(15, 17, 21, .16);
  --shadow-pop:   0 12px 28px -8px rgba(15, 17, 21, .22), 0 2px 6px rgba(15, 17, 21, .06);

  --max-w: 1180px;
  --max-w-narrow: 720px;

  --header-h: 56px;
  --tabbar-h: 60px;

  /* Respect the notch and the home indicator. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-800);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "kern" 1, "liga" 1, "cv11" 1;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5 {
  margin: 0;
  font-weight: 640;
  line-height: 1.15;
  letter-spacing: -0.022em;
  color: var(--ink-900);
  text-wrap: balance;
}

h1 { font-size: clamp(2rem, 1.35rem + 2.6vw, 3.5rem); letter-spacing: -0.034em; }
h2 { font-size: clamp(1.55rem, 1.15rem + 1.5vw, 2.4rem); letter-spacing: -0.03em; }
h3 { font-size: clamp(1.2rem, 1.05rem + 0.5vw, 1.45rem); }
h4 { font-size: 1.0625rem; letter-spacing: -0.015em; }

p { margin: 0 0 var(--s4); }
p:last-child { margin-bottom: 0; }

a { color: var(--accent-deep); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-dark); }

img, svg, video { max-width: 100%; height: auto; display: block; }

ul, ol { margin: 0 0 var(--s4); padding-left: 1.15em; }
li { margin-bottom: var(--s2); }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--s6) 0; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

table { border-collapse: collapse; width: 100%; }

::selection { background: var(--accent); color: #fff; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ------------------------------------------------------------ typography */

/* The small uppercase label above a heading or beside a stat. Used a lot —
   it's the main thing that gives the UI its instrument-panel character. */
.eyebrow {
  font-size: .6875rem;
  font-weight: 660;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-300);
  margin: 0 0 var(--s3);
  display: block;
}
.eyebrow--accent { color: var(--accent); }
.eyebrow--on-dark { color: var(--ink-200); }

.lede {
  font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink-400);
}

.muted { color: var(--ink-300); }
.small { font-size: .875rem; }
.tiny  { font-size: .75rem; }
.strong { font-weight: 620; }

/* Every number that means something operational goes through this. */
.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

.mono { font-family: var(--font-mono); font-size: .9em; }

.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--ink-900); color: #fff; padding: var(--s3) var(--s5);
  border-radius: 0 0 var(--r-sm) 0; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* ----------------------------------------------------------------- brand */
/*
 * The CrewByte wordmark (assets/img/crewbytegrass.png).
 *
 * TWO THINGS TO KNOW BEFORE PLACING IT:
 *
 * 1. It is a DARK-SURFACE ASSET. "crew" is #12876F and "byte" is #FBFEFE, so
 *    on a light background the second half of the word vanishes. Every use
 *    below sits on --ink-900 or darker. For light surfaces (transactional
 *    email, the printed audit pack) a dark-ink variant is needed.
 *
 * 2. The PNG is 2000x702 but the ink occupies only the middle 1548x354 —
 *    roughly 25% transparent padding top and bottom. The visible wordmark is
 *    therefore about HALF the CSS height set here. The values below are
 *    doubled to compensate; if the asset is ever re-exported trimmed, halve
 *    them all.
 */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  text-decoration: none;
  color: inherit;
}
.brand__img {
  display: block;
  width: auto;
  height: 40px;          /* ≈20px of visible wordmark */
  flex: 0 0 auto;
}
.brand:hover { opacity: .85; }

/* A small uppercase qualifier sat next to the wordmark, e.g. "Console". */
.brand__tag {
  font-size: .5625rem;
  font-weight: 680;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--warn-on-dark);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- layout */
.wrap {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--s5);
}
.wrap--narrow { max-width: var(--max-w-narrow); }
.wrap--wide { max-width: 1380px; }

.stack > * + * { margin-top: var(--s4); }
.stack-sm > * + * { margin-top: var(--s2); }
.stack-lg > * + * { margin-top: var(--s6); }

.row {
  display: flex;
  align-items: center;
  gap: var(--s3);
}
.row--between { justify-content: space-between; }
.row--wrap { flex-wrap: wrap; }
.row--top { align-items: flex-start; }
.row--baseline { align-items: baseline; }
.spacer { flex: 1 1 auto; }

.grid { display: grid; gap: var(--s4); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* ---------------------------------------------------------------- surfaces */
.panel {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.panel--sunk { background: var(--paper-sunk); }
.panel--flush { border-radius: 0; border-inline: 0; }
.panel__head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.panel__title { font-size: .9375rem; font-weight: 640; letter-spacing: -.012em; }
.panel__body { padding: var(--s5); }
.panel__body--tight { padding: var(--s4); }
.panel__foot {
  padding: var(--s4) var(--s5);
  border-top: 1px solid var(--line);
  background: var(--paper-sunk);
  border-radius: 0 0 var(--r-md) var(--r-md);
}

/* A row of hairline-separated items — the workhorse list pattern. */
.list { list-style: none; margin: 0; padding: 0; }
.list > li { margin: 0; border-bottom: 1px solid var(--line); }
.list > li:last-child { border-bottom: 0; }

.list-item {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4) var(--s5);
  min-height: 60px;
  text-decoration: none;
  color: inherit;
  transition: background .12s ease;
}
a.list-item:hover { background: var(--paper-sunk); }
.list-item__main { min-width: 0; flex: 1; }
.list-item__title { font-weight: 590; font-size: .9375rem; color: var(--ink-900); }
.list-item__meta { font-size: .8125rem; color: var(--ink-300); margin-top: 2px; }

/* ---------------------------------------------------------------- buttons */
.btn {
  --btn-bg: var(--ink-900);
  --btn-fg: #fff;
  --btn-border: var(--ink-900);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 44px;
  padding: 11px 20px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  border-radius: var(--r-sm);
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.005em;
  text-decoration: none;
  white-space: nowrap;
  transition: background .14s ease, border-color .14s ease, transform .06s ease, opacity .14s ease;
}
.btn:hover { background: var(--ink-700); border-color: var(--ink-700); color: #fff; }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn.is-disabled { opacity: .45; pointer-events: none; }

.btn--accent { --btn-bg: var(--accent); --btn-border: var(--accent); }
.btn--accent:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink-800);
  --btn-border: var(--line-strong);
}
.btn--ghost:hover { background: var(--paper-sunk); color: var(--ink-900); border-color: var(--ink-300); }

.btn--quiet {
  --btn-bg: transparent;
  --btn-fg: var(--ink-400);
  --btn-border: transparent;
}
.btn--quiet:hover { background: var(--paper-sunk); color: var(--ink-900); border-color: transparent; }

.btn--danger { --btn-bg: var(--bad); --btn-border: var(--bad); }
.btn--danger:hover { background: #99301F; border-color: #99301F; }

.btn--on-dark {
  --btn-bg: transparent;
  --btn-fg: #fff;
  --btn-border: rgba(255,255,255,.28);
}
.btn--on-dark:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.5); color: #fff; }

.btn--lg { min-height: 52px; padding: 14px 28px; font-size: 1rem; }
.btn--sm { min-height: 36px; padding: 7px 14px; font-size: .8125rem; }
.btn--block { display: flex; width: 100%; }
.btn--icon { padding: 0; width: 44px; min-height: 44px; }

.btn-group { display: inline-flex; gap: var(--s2); flex-wrap: wrap; }

/* ----------------------------------------------------------------- forms */
.field { margin-bottom: var(--s5); }
.field:last-child { margin-bottom: 0; }

.label {
  display: block;
  font-size: .8125rem;
  font-weight: 620;
  color: var(--ink-600);
  margin-bottom: var(--s2);
  letter-spacing: -.005em;
}
.label__hint { font-weight: 450; color: var(--ink-300); }

.input, .select, .textarea {
  width: 100%;
  min-height: 46px;
  padding: 11px 13px;
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 1rem;               /* 16px stops iOS zooming on focus */
  color: var(--ink-900);
  transition: border-color .14s ease, box-shadow .14s ease;
  -webkit-appearance: none;
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: var(--ink-200); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
.input:disabled, .select:disabled, .textarea:disabled {
  background: var(--paper-sunk);
  color: var(--ink-300);
  cursor: not-allowed;
}
.textarea { min-height: 96px; resize: vertical; line-height: 1.5; }

.select {
  padding-right: 38px;
  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 1.5 6 6.5l5-5' stroke='%23575F6D' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
}

.input--num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -.01em;
}

.field-error {
  display: block;
  margin-top: var(--s2);
  font-size: .8125rem;
  font-weight: 550;
  color: var(--bad);
}
.field.has-error .input,
.field.has-error .select,
.field.has-error .textarea { border-color: var(--bad); }
.field.has-error .input:focus { box-shadow: 0 0 0 3px var(--bad-tint); }

.help { margin-top: var(--s2); font-size: .8125rem; color: var(--ink-300); line-height: 1.5; }

/* Checkboxes and radios — big enough for a thumb, square for checks. */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s3) 0;
  cursor: pointer;
}
.check input[type="checkbox"],
.check input[type="radio"] {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  margin: 1px 0 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.check__text { font-size: .9375rem; line-height: 1.45; }
.check__note { display: block; font-size: .8125rem; color: var(--ink-300); margin-top: 2px; }

/* Card-style selectable option (role picker, segment picker). */
.choice {
  display: block;
  position: relative;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: var(--s4);
  cursor: pointer;
  background: var(--paper-raised);
  transition: border-color .14s ease, background .14s ease;
}
.choice:hover { border-color: var(--ink-300); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice__title { font-weight: 620; font-size: .9375rem; display: flex; align-items: center; gap: var(--s2); }
.choice__desc { font-size: .8125rem; color: var(--ink-300); margin-top: 3px; line-height: 1.45; }
.choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-tint);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.choice:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Segmented control — used for date range, status filters. */
.segmented {
  display: inline-flex;
  padding: 3px;
  background: var(--paper-sunk);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  gap: 2px;
}
.segmented a, .segmented button {
  padding: 7px 13px;
  border: 0;
  background: transparent;
  border-radius: 3px;
  font-size: .8125rem;
  font-weight: 580;
  color: var(--ink-400);
  text-decoration: none;
  white-space: nowrap;
}
.segmented a:hover, .segmented button:hover { color: var(--ink-900); }
.segmented .is-active {
  background: var(--paper-raised);
  color: var(--ink-900);
  box-shadow: 0 1px 2px rgba(15,17,21,.08);
}

/* --------------------------------------------------------------- badges */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: .6875rem;
  font-weight: 660;
  letter-spacing: .045em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--paper-deep);
  color: var(--ink-400);
  border: 1px solid transparent;
}
.badge--ok   { background: var(--accent-tint); color: var(--accent-dark); }
.badge--warn { background: var(--warn-tint);  color: var(--warn); }
.badge--bad  { background: var(--bad-tint);   color: var(--bad); }
.badge--info { background: var(--info-tint);  color: var(--info); }
.badge--muted{ background: var(--paper-deep); color: var(--ink-300); }
.badge--outline { background: transparent; border-color: var(--line-strong); color: var(--ink-400); }

.badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Square status tick used in run lists. */
.tick {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  border-radius: var(--r-xs);
  border: 1.5px solid var(--line-strong);
  display: grid;
  place-items: center;
  background: var(--paper-raised);
}
.tick--pass { background: var(--accent); border-color: var(--accent); color: #fff; }
.tick--fail { background: var(--bad); border-color: var(--bad); color: #fff; }
.tick--na   { background: var(--paper-deep); border-color: var(--line-strong); color: var(--ink-300); }

/* ---------------------------------------------------------------- stats */
.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s4) var(--s5);
}
.stat__label {
  font-size: .6875rem;
  font-weight: 640;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--ink-300);
}
.stat__value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.75rem;
  font-weight: 620;
  letter-spacing: -.03em;
  color: var(--ink-900);
  line-height: 1.05;
}
.stat__value--ok  { color: var(--accent-deep); }
.stat__value--warn{ color: var(--warn); }
.stat__value--bad { color: var(--bad); }
.stat__note { font-size: .75rem; color: var(--ink-300); }

/* A hairline-divided strip of stats. */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.stat-strip > .stat + .stat { border-left: 1px solid var(--line); }
@media (max-width: 640px) {
  .stat-strip { grid-template-columns: repeat(2, 1fr); }
  .stat-strip > .stat { border-top: 1px solid var(--line); }
  .stat-strip > .stat:nth-child(-n+2) { border-top: 0; }
  .stat-strip > .stat:nth-child(odd) { border-left: 0 !important; }
}

/* ---------------------------------------------------------------- meter */
.meter {
  position: relative;
  height: 6px;
  background: var(--paper-deep);
  border-radius: 999px;
  overflow: hidden;
}
.meter__fill {
  position: absolute; inset: 0 auto 0 0;
  background: var(--accent);
  border-radius: 999px;
  transition: width .35s cubic-bezier(.2,.7,.3,1);
}
.meter__fill--warn { background: var(--warn); }
.meter__fill--bad  { background: var(--bad); }
.meter--tall { height: 10px; }

/* ---------------------------------------------------------------- tables */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.table { font-size: .875rem; }
.table th {
  text-align: left;
  padding: var(--s3) var(--s4);
  font-size: .6875rem;
  font-weight: 660;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--ink-300);
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
  background: var(--paper-sunk);
}
.table td {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
.table tbody tr:hover { background: var(--paper-sunk); }
.table tbody tr:last-child td { border-bottom: 0; }
.table td.num, .table th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ empty state */
.empty {
  text-align: center;
  padding: var(--s9) var(--s5);
  max-width: 420px;
  margin-inline: auto;
}
.empty__mark {
  width: 52px; height: 52px;
  margin: 0 auto var(--s4);
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--r-md);
  display: grid;
  place-items: center;
  color: var(--ink-200);
}
.empty__title { font-size: 1.0625rem; font-weight: 640; margin-bottom: var(--s2); }
.empty__body { font-size: .9375rem; color: var(--ink-300); line-height: 1.6; margin-bottom: var(--s5); }

/* ---------------------------------------------------------------- flashes */
.flash-stack {
  position: fixed;
  left: 50%;
  top: calc(var(--safe-top) + 12px);
  transform: translateX(-50%);
  z-index: 200;
  width: min(560px, calc(100vw - 24px));
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  pointer-events: none;
}
.flash {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--ink-900);
  color: #fff;
  border-radius: var(--r-sm);
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.45;
  box-shadow: var(--shadow-pop);
  pointer-events: auto;
  animation: flash-in .28s cubic-bezier(.2,.8,.3,1);
}
.flash__bar { width: 3px; align-self: stretch; border-radius: 2px; background: var(--accent-on-dark); flex: 0 0 auto; }
.flash--error .flash__bar { background: var(--bad-on-dark); }
.flash--warning .flash__bar { background: var(--warn-on-dark); }
.flash__close {
  background: none; border: 0; color: rgba(255,255,255,.5);
  padding: 0 0 0 var(--s2); font-size: 1.1rem; line-height: 1;
}
.flash__close:hover { color: #fff; }
@keyframes flash-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Inline (non-toast) notice block. */
.notice {
  display: flex;
  gap: var(--s3);
  padding: var(--s4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--paper-sunk);
  font-size: .875rem;
  line-height: 1.55;
}
.notice__bar { width: 3px; border-radius: 2px; background: var(--ink-300); flex: 0 0 auto; }
.notice--ok   { background: var(--accent-tint); border-color: var(--accent-tint-strong); }
.notice--ok   .notice__bar { background: var(--accent); }
.notice--warn { background: var(--warn-tint); border-color: #EBD9B7; }
.notice--warn .notice__bar { background: var(--warn); }
.notice--bad  { background: var(--bad-tint); border-color: #EFCEC9; }
.notice--bad  .notice__bar { background: var(--bad); }
.notice__title { font-weight: 640; margin-bottom: 2px; }

/* ---------------------------------------------------------------- dialog */
.sheet-backdrop {
  position: fixed; inset: 0;
  background: rgba(15,17,21,.45);
  z-index: 300;
  opacity: 0;
  animation: fade-in .18s ease forwards;
}
@keyframes fade-in { to { opacity: 1; } }

.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 301;
  background: var(--paper-raised);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--shadow-sheet);
  padding: var(--s5) var(--s5) calc(var(--s5) + var(--safe-bottom));
  max-height: 88vh;
  overflow-y: auto;
  animation: sheet-up .26s cubic-bezier(.2,.8,.3,1);
}
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
.sheet__grip {
  width: 36px; height: 4px; border-radius: 2px;
  background: var(--line-strong);
  margin: 0 auto var(--s4);
}
.sheet__title { font-size: 1.125rem; font-weight: 650; margin-bottom: var(--s2); }

@media (min-width: 720px) {
  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    transform: translate(-50%, -50%);
    width: min(520px, calc(100vw - 48px));
    border-radius: var(--r-lg);
    animation: pop-in .2s cubic-bezier(.2,.8,.3,1);
  }
  @keyframes pop-in {
    from { opacity: 0; transform: translate(-50%, -46%) scale(.97); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  }
  .sheet__grip { display: none; }
}

/* --------------------------------------------------------------- dark ctx */
/* Applied to any dark region (hero, nav rail, console). */
.on-dark {
  color: rgba(248,247,244,.72);
  background: var(--ink-900);
}
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4, .on-dark .strong { color: #F8F7F4; }
.on-dark a { color: var(--accent-on-dark); }
.on-dark .muted { color: var(--ink-200); }
.on-dark .panel {
  background: var(--ink-800);
  border-color: var(--line-dark);
}
.on-dark .panel__head, .on-dark .list > li { border-color: var(--line-dark); }
.on-dark .stat__value { color: #F8F7F4; }
.on-dark .stat__label, .on-dark .stat__note { color: var(--ink-200); }

/* ---------------------------------------------------------------- utils */
.hide { display: none !important; }
@media (max-width: 767px)  { .hide-sm { display: none !important; } }
@media (min-width: 768px)  { .hide-lg { display: none !important; } }

.mt0 { margin-top: 0 !important; }
.mb0 { margin-bottom: 0 !important; }
.mt2 { margin-top: var(--s2); }
.mt3 { margin-top: var(--s3); }
.mt4 { margin-top: var(--s4); }
.mt5 { margin-top: var(--s5); }
.mt6 { margin-top: var(--s6); }
.mt7 { margin-top: var(--s7); }
.mb4 { margin-bottom: var(--s4); }
.mb6 { margin-bottom: var(--s6); }

.text-center { text-align: center; }
.text-right { text-align: right; }
.full { width: 100%; }

/* Thin diagonal hatch — marks "no data yet" zones without shouting. */
.hatch {
  background-image: repeating-linear-gradient(
    45deg,
    transparent, transparent 5px,
    var(--line) 5px, var(--line) 6px
  );
}

/* ==========================================================================
   SHARED LAYOUT + COMPONENTS
   These live here, not in app.css, because more than one surface loads them:
   the console renders support threads and page heads too, and it only ever
   loads base.css + console.css. Everything below is token-driven, so a dark
   surface gets the dark treatment by re-pointing --paper-* rather than by
   restating each rule (see .c-main in console.css).
   ========================================================================== */

/* Spacing scale. mb0/mb4/mb6 lived here already; the gaps in between were
   being used in markup and silently doing nothing. */
.mb2 { margin-bottom: var(--s2); }
.mb5 { margin-bottom: var(--s5); }
.mb7 { margin-bottom: var(--s7); }

/* Two-up form rows. Was in site.css only, so every form on the app and the
   console stacked in one column no matter what the markup asked for. */
.form-grid { display: grid; gap: var(--s4); }
@media (min-width: 620px) { .form-grid--2 { grid-template-columns: 1fr 1fr; } }
.hp-field { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }
@media (min-width: 620px) { .form-grid--3 { grid-template-columns: repeat(3, 1fr); } }

.builder-grid { display: grid; gap: var(--s3); }
@media (min-width: 640px) { .builder-grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 640px) { .builder-grid--2 { grid-template-columns: repeat(2, 1fr); } }


.page-head { margin-bottom: var(--s6); }
.page-head__row { display: flex; align-items: flex-start; gap: var(--s4); flex-wrap: wrap; }
.page-head h1 {
  font-size: clamp(1.375rem, 1.2rem + .8vw, 1.875rem);
  letter-spacing: -.028em;
  margin-bottom: var(--s2);
}
.page-head__sub { color: var(--ink-300); font-size: .9375rem; }


.back-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .8125rem;
  font-weight: 570;
  color: var(--ink-400);
  text-decoration: none;
}
.back-link:hover { color: var(--ink-900); }


/* ==========================================================================
   SUPPORT TICKETS
   The message thread, shared by the app side and the console.
   ========================================================================== */

.thread { display: grid; gap: var(--s4); }

.msg {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper-raised);
  overflow: hidden;
}

/* Ours vs theirs is carried by a left edge rather than by alignment: a chat
   layout with alternating sides reads as a messaging app, and this is a record
   people print and attach to complaints. */
.msg--support { border-left: 3px solid var(--accent); }
.msg--user    { border-left: 3px solid var(--line-strong); }
.msg--system  { border-left: 3px solid var(--ink-200); background: var(--paper-sunk); }

/* Console only. Nothing on the customer side ever fetches these rows. */
.msg--internal {
  background: var(--warn-tint);
  border-color: #EBD9B7;
  border-left-color: var(--warn);
}

.msg__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--line);
  background: var(--paper-sunk);
}
.msg--internal .msg__head { background: transparent; border-bottom-color: #EBD9B7; }
.msg--system .msg__head { background: transparent; }

.msg__who {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: .8125rem;
  font-weight: 640;
  color: var(--ink-900);
}
.msg__when {
  font-family: var(--font-mono);
  font-size: .6875rem;
  letter-spacing: .04em;
  color: var(--ink-300);
  white-space: nowrap;
}

.msg__body { padding: var(--s5); }
.msg__body p { font-size: .9375rem; line-height: 1.65; color: var(--ink-600); }
.msg__body p:last-child { margin-bottom: 0; }

/* A system line ("closed by …") is a marginal note, not a message. */
.msg--system .msg__body { padding: var(--s3) var(--s5); }
.msg--system .msg__body p { font-size: .8125rem; color: var(--ink-300); font-style: italic; }

/* Initials badge. Shared: the console user page shows one too. */

.avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: .75rem;
  font-weight: 680;
  letter-spacing: .02em;
  flex: 0 0 auto;
  text-decoration: none;
}
.avatar--lg { width: 44px; height: 44px; font-size: .9375rem; }
.avatar--muted { background: var(--paper-deep); color: var(--ink-400); }

/* Button row closing a form, with a rule above it. */

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
}

/* Label/value pairs. Shared: the console partner page uses one too. */
.kv { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: var(--s2) var(--s5); font-size: .875rem; }
.kv dt { color: var(--ink-300); }
.kv dd { margin: 0; color: var(--ink-900); font-weight: 540; }

/* Guidance lists — brand rules, "how it works", do-and-do-not. A drawn tick
   rather than a disc or a glyph: it says "this is true of you" rather than
   "item n of a list", and a CSS shape needs no font to be present to render. */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.ticks li {
  position: relative;
  padding-left: 21px;
  font-size: .875rem;
  line-height: 1.55;
  color: var(--ink-600);
}
.ticks li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: .34em;
  width: 5px;
  height: 9px;
  border: solid var(--accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* ===========================================================================
   Badges
   ===========================================================================
   Shown next to a name on the community and in the console, so the rules live
   here rather than in either surface's sheet — a badge that looked different
   in the two places would read as two different things.

   Tones are token pairs, never raw hex at the use site, so the console's dark
   surface re-points them the same way it re-points everything else.
   ------------------------------------------------------------------------- */

.cbadge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border: 1px solid var(--cbadge-line, var(--line-strong));
  border-radius: 999px;
  background: var(--cbadge-bg, var(--paper-sunk));
  color: var(--cbadge-ink, var(--ink-600));
  font-size: .6875rem;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .01em;
  white-space: nowrap;
  vertical-align: middle;
}

/* Staff — an identity claim, so these carry weight. */
.cbadge--team {
  --cbadge-bg:   var(--accent);
  --cbadge-ink:  #FFFFFF;
  --cbadge-line: var(--accent-deep);
}
.cbadge--dev {
  --cbadge-bg:   var(--ink-800);
  --cbadge-ink:  #FFFFFF;
  --cbadge-line: var(--ink-700);
}
.cbadge--partner {
  --cbadge-bg:   var(--info-tint);
  --cbadge-ink:  var(--info);
  --cbadge-line: #C3D5E6;
}
.cbadge--verified {
  --cbadge-bg:   var(--accent-tint);
  --cbadge-ink:  var(--accent-deep);
  --cbadge-line: var(--accent-tint-strong);
}
.cbadge--mod {
  --cbadge-bg:   var(--warn-tint);
  --cbadge-ink:  var(--warn);
  --cbadge-line: #E8D3AE;
}

/* Awards — earned, so quieter than the staff set on purpose. A wall of gold
   next to every name makes the one that matters invisible. */
.cbadge--bronze { --cbadge-bg: #F4EDE4; --cbadge-ink: #7A5327; --cbadge-line: #E2D2BC; }
.cbadge--silver { --cbadge-bg: #EFF1F3; --cbadge-ink: #4A5561; --cbadge-line: #D5DAE0; }
.cbadge--gold   { --cbadge-bg: #FAF1D8; --cbadge-ink: #7C5F13; --cbadge-line: #E8D79B; }

.cbadge--sm { padding: 1px 6px; font-size: .625rem; }

/* A row of them wraps rather than pushing the name off the line. */
.cbadges {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  vertical-align: middle;
}

/* A set of badges to tick, rather than a dropdown that grants one at a time.
   Shown in both the console and the moderator queue, so it lives here. */
.badgepick { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.badgepick__opt { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.badgepick__opt input { margin: 0; }
.badgepick__opt.is-held { opacity: .45; cursor: default; }
