/* =============================================================================
   OperatorHub Plus — platform design system

   Implements "OperatorHub Plus - Style Guide.dc.html" and
   "OperatorHub Plus - Login Page.dc.html" (Claude Design project
   58c62761-142d-426f-9476-7d481aea4b35). Read those before changing any visual
   decision here — they carry the reasoning, not just the values.

   TWO THEME LAYERS. Everything in this file is LAYER 1, the platform: login,
   tile menu, tool navigation, client settings, ops review, platform admin. It
   is fixed — our green, our type, our components, never themed by a client, and
   no operator logo in the chrome. Layer 2 (guest-facing waiver pages) is themed
   per client from the three-token model and lives in
   pages-ophub-waivers-guest. A component built for one is not automatically
   valid in the other.

   Colour is authored in oklch so lightness stays perceptually even across hues.
   There is no build step to emit fallbacks, so each token declares hex first and
   oklch second: a browser that cannot parse oklch keeps the hex and everything
   still works.

   Three rules that are easy to undo by accident:

   1. --c-primary is NEVER a large background fill and never green text on
      light — it is 3.71:1 on white. Buttons carry white on it; green *text*
      uses --c-primary-deep (6.15:1+).
   2. The plus lifts to --c-plus on navy. The primary green goes muddy against a
      dark ground, so the lockup's plus is a different green by context, not by
      accident.
   3. Borders carry structure, not shadows. Cards, tables and tiles are flat —
      a 1px border, no shadow. Shadow is only for things genuinely above the
      page (dropdowns, modals, sheets).
   ========================================================================== */

:root {
  /* ── Green ─────────────────────────────────────────────────────────────── */
  --c-primary: #219761;            /* buttons, active nav, focus rings          */
  --c-primary: oklch(0.60 0.13 158);
  --c-primary-hover: #067D4D;
  --c-primary-hover: oklch(0.52 0.12 158);
  --c-primary-deep: #0E653F;       /* green TEXT on light — clears 4.5:1        */
  --c-primary-deep: oklch(0.45 0.10 158);
  --c-primary-soft: #DFF5E7;       /* tinted panels, badges, active tile fill   */
  --c-primary-soft: oklch(0.95 0.03 158);
  --c-plus: #37C080;               /* the plus, on navy only                    */
  --c-plus: oklch(0.72 0.15 158);
  --c-focus-ring: #C3E9D2;
  --c-focus-ring: oklch(0.90 0.05 158);

  /* ── Ink ───────────────────────────────────────────────────────────────── */
  --c-ink: #16202B;                /* headings, body, navy panel fill           */
  --c-ink: oklch(0.24 0.025 250);
  --c-ink-label: #333C45;
  --c-ink-label: oklch(0.35 0.02 250);
  --c-ink-body: #4D5660;
  --c-ink-body: oklch(0.45 0.02 250);
  --c-ink-muted: #555F69;
  --c-ink-muted: oklch(0.48 0.02 250);
  --c-on-navy-dim: #BDC5CE;
  --c-on-navy-dim: oklch(0.82 0.015 250);
  --c-ink-raised: #242F3A;         /* control fill on the navy chrome           */
  --c-ink-raised: oklch(0.30 0.025 250);
  --c-ink-line: #404952;           /* its hairline                              */
  --c-ink-line: oklch(0.40 0.02 250);

  /* ── Ground ────────────────────────────────────────────────────────────── */
  --c-canvas: #F8FBF9;             /* a trace of green, so white reads warm     */
  --c-canvas: oklch(0.985 0.004 150);
  --c-surface: #ffffff;
  --c-border: #DBDEE2;
  --c-border: oklch(0.90 0.006 250);
  --c-border-input: #CDD1D6;
  --c-border-input: oklch(0.86 0.008 250);
  --c-rule: #E5E8EC;
  --c-rule: oklch(0.93 0.006 250);

  /* ── Status. NEVER themed by a client — a completed waiver is green whatever
        the operator's brand is. ─────────────────────────────────────────── */
  --c-success: var(--c-primary);
  --c-info: #3F83CB;
  --c-info: oklch(0.60 0.13 252);
  --c-warning: #E1A035;
  --c-warning: oklch(0.75 0.14 75);
  --c-danger: #C84341;
  --c-danger: oklch(0.57 0.17 25);

  --c-link: #077045;
  --c-link: oklch(0.48 0.11 158);
  --c-link-hover: #00502F;
  --c-link-hover: oklch(0.38 0.09 158);

  /* ── Type ──────────────────────────────────────────────────────────────── */
  --font-head: Archivo, "Helvetica Neue", Arial, sans-serif;
  --font-body: "Instrument Sans", system-ui, -apple-system, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "Courier New", monospace;

  /* ── Space (4px base) and radius ───────────────────────────────────────── */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-6: 24px; --s-10: 40px; --s-16: 64px;
  --r-input: 8px;   /* inputs, buttons */
  --r-card: 12px;   /* cards, tiles    */
  --r-modal: 16px;  /* modals, sheets  */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--c-canvas);
  color: var(--c-ink);
  font: 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--c-link); text-decoration: none; }
a:hover { color: var(--c-link-hover); text-decoration: underline; }

.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;
}

/* Keyboard focus only, per the guide: 2px solid primary, offset 2px. */
:where(a, button, input, select, [tabindex]):focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

/* ── The lockup ───────────────────────────────────────────────────────────
   Set in type rather than shipped as an image, so it stays sharp at any size
   and the plus can take its context colour. "Operator" bold, "Hub" regular,
   plus bold — one optical gap, never a space. Never stacked; it is a single
   line at all sizes. */

.lockup {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--font-head);
  letter-spacing: -0.035em;
  line-height: 1;
  white-space: nowrap;
}

.lockup b { font-weight: 700; }
.lockup i { font-weight: 400; font-style: normal; }

/* One optical gap, never a space. The plus is part of the word. */
.lockup__plus { font-weight: 700; padding-left: 0.09em; }

.lockup--on-navy b,
.lockup--on-navy i { color: #ffffff; }
.lockup--on-navy .lockup__plus { color: var(--c-plus); }

/* On light, the plus takes --c-primary. It is a mark, not text, so its 3.71:1
   is fine — and the wordmark beside it carries the meaning for a screen reader. */
.lockup--on-light b,
.lockup--on-light i { color: var(--c-ink); }
.lockup--on-light .lockup__plus { color: var(--c-primary); }

/* =============================================================================
   Login — split panel. Navy fixed at 620px, form on white.
   Below 900px the navy becomes a 260px header band; the full hero never stacks
   above the fold on a phone.
   ========================================================================== */

.login {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 620px 1fr;
  background: var(--c-surface);
}

.login__hero {
  position: relative;
  background: var(--c-ink);
  overflow: hidden;
  padding: 56px 60px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Scrims. They do nothing over flat navy, and everything the day a photograph
   is dropped behind them — the lockup and headline stay legible on a bright
   image, so the panel still reads as ours rather than as a stock hero.
   Set --login-photo to a url() to use one. */
.login__hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, oklch(0.18 0.02 250 / 0.72) 0%, oklch(0.18 0.02 250 / 0.28) 55%, transparent 100%),
    linear-gradient(160deg, oklch(0.24 0.025 250 / 0.28) 0%, oklch(0.24 0.025 250 / 0.40) 55%, oklch(0.20 0.03 158 / 0.52) 100%),
    var(--login-photo, none) center / cover no-repeat;
  pointer-events: none;
}

.login__hero > * { position: relative; }

.login__lockup { font-size: 30px; }

.login__pitch {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.login__headline {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 46px;
  line-height: 1.08;
  letter-spacing: -0.032em;
  color: #ffffff;
  max-width: 21ch;
}

.login__sub {
  margin: 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--c-on-navy-dim);
  max-width: 38ch;
}

.login__panel {
  padding: 0 96px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 34px;
}

.login__title {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 38px;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.login__blurb {
  margin: 12px 0 0;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--c-ink-body);
  max-width: 44ch;
}

.login__rule {
  height: 1px;
  background: var(--c-rule);
}

.login__foot {
  display: flex;
  flex-direction: column;
  gap: 14px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--c-ink-body);
  max-width: 44ch;
}

.login__foot p { margin: 0; }

@media (max-width: 900px) {
  .login { grid-template-columns: 1fr; }

  .login__hero {
    height: 260px;
    padding: 28px 24px;
  }

  .login__lockup { font-size: 23px; }
  .login__sub { display: none; }

  .login__headline {
    font-size: 27px;
    line-height: 1.15;
    letter-spacing: -0.03em;
    max-width: 18ch;
  }

  .login__panel {
    padding: 32px 24px;
    gap: 26px;
    justify-content: flex-start;
  }

  .login__title { font-size: 27px; letter-spacing: -0.028em; }
  .login__blurb { font-size: 15px; }
}

/* ── Forms ────────────────────────────────────────────────────────────────
   Labels above fields, always visible — never placeholder-as-label. Help text
   and validation share one slot so nothing reflows when an error appears. */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

label {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--c-ink-label);
}

input[type="email"],
input[type="text"] {
  width: 100%;
  font-family: var(--font-body);
  font-size: 16px;          /* 16px minimum, or iOS zooms the page on focus */
  padding: 15px 16px;
  border-radius: var(--r-input);
  border: 1px solid var(--c-border-input);
  background: var(--c-surface);
  color: var(--c-ink);
}

input::placeholder { color: var(--c-ink-muted); opacity: 0.75; }

input:focus {
  border-color: var(--c-primary);
  outline: 2px solid var(--c-focus-ring);
  outline-offset: 0;
}

/* Stacks a form's controls at the 'between controls' step of the space scale. */
.form-stack {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.field--code { gap: 10px; }

/* Body copy outside the login panel. */
.prose {
  margin: 0 0 var(--s-6);
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--c-ink-body);
  max-width: 60ch;
}

/* One slot for help and validation, so the button never jumps. */
.slot {
  min-height: 1.35em;
  margin: 0;
  font-size: 14px;
  line-height: 1.35;
  color: var(--c-ink-muted);
}

.slot--error { color: var(--c-danger); }

/* ── Buttons ──────────────────────────────────────────────────────────────
   One primary per view. Medium (42px) is the default; the login's committing
   action is large. No touch target below 44px. */

.btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 16px;
  padding: 16px 26px;
  min-height: 50px;
  border-radius: var(--r-input);
  border: none;
  background: var(--c-primary);
  color: #ffffff;
  cursor: pointer;
  transition: background 120ms ease;
}

.btn:hover { background: var(--c-primary-hover); }
.btn[disabled] { opacity: 0.5; cursor: default; }

.btn--ghost {
  padding: 0;
  min-height: 0;
  font-size: 14.5px;
  font-weight: 400;
  background: none;
  color: var(--c-link);
  text-decoration: none;
}

.btn--ghost:hover { background: none; color: var(--c-link-hover); text-decoration: underline; }

/* ── Six-digit code ───────────────────────────────────────────────────────
   Six single-character inputs, not one field. 58x66 — past the 44px touch
   minimum and wide enough for the browser's one-time-code autofill. Mono,
   because a code is operational data: something you read aloud or copy. */

.code {
  display: flex;
  gap: 10px;
}

.code__box {
  width: 58px;
  height: 66px;
  padding: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 26px;
  border: 1px solid var(--c-border-input);
  border-radius: var(--r-input);
  background: var(--c-surface);
  color: var(--c-ink);
}

.code__box:focus {
  border: 2px solid var(--c-primary);
  outline: 2px solid var(--c-focus-ring);
  outline-offset: 0;
}

@media (max-width: 420px) {
  .code { gap: 6px; }
  .code__box { width: 100%; height: 58px; font-size: 22px; }
}

/* The address the code went to — operational data, so mono. */
.mono {
  font-family: var(--font-mono);
  font-size: 0.94em;
  color: var(--c-ink);
}

/* =============================================================================
   App shell. Directional: the rail and tool pages will change as the build
   goes on. What holds is the frame — navy chrome, the in-app lockup, the client
   selector in the header, content on the light canvas.
   ========================================================================== */

.appbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-6);
  background: var(--c-ink);
}

.appbar__lockup { font-size: 20px; }

.appbar__right {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  font-size: 14px;
  color: var(--c-on-navy-dim);
}

.appbar__who { display: flex; flex-direction: column; line-height: 1.25; }
.appbar__who b { color: #ffffff; font-weight: 500; }

.appbar__role {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-on-navy-dim);
}

.appbar .btn--ghost { color: var(--c-on-navy-dim); }
.appbar .btn--ghost:hover { color: #ffffff; }

select {
  font-family: var(--font-body);
  font-size: 14px;
  padding: 9px 12px;
  border-radius: var(--r-input);
  border: 1px solid var(--c-ink-line);
  background: var(--c-ink-raised);
  color: #ffffff;
}

.content {
  max-width: 1060px;
  margin: 0 auto;
  padding: var(--s-10) var(--s-6) var(--s-16);
}

.page-title {
  margin: 0 0 var(--s-6);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 44px;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-ink-muted);
}

.notice {
  margin: 0 0 var(--s-6);
  padding: var(--s-4) var(--s-4) var(--s-4) var(--s-3);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--c-ink-body);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-warning);
  border-radius: var(--r-card);
}

/* ── Tool tile ────────────────────────────────────────────────────────────
   The landing menu IS the portal, and for a while it holds one live tile and a
   few promises — so each tile carries a status line rather than being a bare
   icon and label. Monogram, not illustration: a letter in a rounded square,
   tinted green when active and grey when not. */

.tiles {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
}

.tile {
  display: grid;
  gap: var(--s-3);
  align-content: start;
  padding: var(--s-6);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-card);
  color: inherit;
  text-decoration: none;
}

/* Raised only on hover of something actually interactive. */
a.tile:hover {
  border-color: var(--c-primary);
  box-shadow: 0 6px 20px rgba(22, 32, 43, 0.08);
  box-shadow: 0 6px 20px oklch(0.24 0.025 250 / 0.08);
  text-decoration: none;
}

.tile__mono {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 20px;
  background: var(--c-primary-soft);
  color: var(--c-primary-deep);
}

.tile__name {
  margin: 0;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.26;
  letter-spacing: -0.015em;
}

.tile__desc {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--c-ink-body);
}

/* The status line is the reason to click. A tile with nothing to report says
   so — it never says nothing. */
.tile__status {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--c-primary-deep);
}

/* Coming tiles are dashed and unclickable. They set expectations without
   pretending to be features — two maximum on screen, or the portal reads as
   vapour. */
.tile--coming {
  border-style: dashed;
  background: transparent;
}

.tile--coming .tile__mono {
  background: var(--c-rule);
  color: var(--c-ink-muted);
}

.tile--coming .tile__name { color: var(--c-ink-body); }
.tile--coming .tile__status { color: var(--c-ink-muted); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
