/* The authenticated application style layer.
 *
 * 🚨 **A third stylesheet is a deliberate choice, not an accident.** `styles.css` is the legacy
 * marketing sheet (radius 16–20, hex literals, a ratchet that may only shrink) and `kit.css` is the
 * public identity system. Authenticated Haba needs its own layer because it is a different product
 * surface with different rules, and because the alternative — more overrides piled onto the
 * marketing CSS — is exactly the "exception swamp" this rebuild exists to end.
 *
 * ⚠️ **Nothing here styles a public page.** Every selector is scoped under `.app` or an `app-*`
 * class, so the marketing site cannot be disturbed by a change made for a member screen.
 *
 * Rules inherited from the kit and enforced by `scripts/check-ui-rules.mjs`: radius 0 everywhere,
 * no decorative shadow, colour only from brand tokens, no letter-spacing on the display face.
 *
 * The scales are the Claude Design final spec (HANDOFF-R2.md §4): seven type sizes replacing the 19
 * the audit measured, eight spacing steps, four grounds and no elevation.
 */

.app {
  /* Type: seven sizes. ⚠️ Phone steps display and title down one, handled at the breakpoint. */
  --t-display: 40px;
  --t-display-lh: 44px;
  --t-title: 32px;
  --t-title-lh: 40px;
  --t-heading: 24px;
  --t-heading-lh: 32px;
  --t-lead: 20px;
  --t-lead-lh: 28px;
  --t-body: 16px;
  --t-body-lh: 24px;
  --t-small: 14px;
  --t-small-lh: 20px;
  --t-micro: 12px;
  --t-micro-lh: 16px;

  /* Space: eight steps. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-6: 24px;
  --s-8: 32px;
  --s-12: 48px;
  --s-16: 64px;

  /* Four grounds, no elevation. Separation comes from ground and rule, never from a shadow. */
  --ground-paper: var(--brand-paper);
  --ground-sheet: var(--brand-card-raised);
  --ground-sunken: var(--brand-sunken);
  --ground-ink: var(--brand-ink);

  --app-content: 1120px;
  --app-pad: 40px;
  --app-header-h: 64px;
  --hit: 44px;
  --hit-primary: 56px;

  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--ground-paper);
  color: var(--brand-ink);
  font-family: var(--brand-sans);
  font-size: var(--t-body);
  line-height: var(--t-body-lh);
}

.app-main {
  flex: 1 1 auto;
  width: 100%;
  max-width: calc(var(--app-content) + var(--app-pad) * 2);
  margin: 0 auto;
  padding: var(--s-12) var(--app-pad) var(--s-16);
}

/* ── Shell ──────────────────────────────────────────────────────────────────────────────────── */

/* ⚠️ Paper, not ink. The authenticated header is part of the application surface; the ink band is
   the marketing site's signature and carrying it in here is what made the product look like a
   website with tooling inside it. */
.app-header {
  display: flex;
  align-items: center;
  gap: var(--s-8);
  height: var(--app-header-h);
  padding: 0 var(--app-pad);
  border-bottom: 1px solid var(--brand-rule);
  background: var(--ground-paper);
}

.app-brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  color: var(--brand-ink);
  font-family: var(--brand-display);
  font-size: 24px;
  line-height: 24px;
  text-decoration: none;
}

.app-nav {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  margin-right: auto;
}

/* One destination does not need a nav bar; Home is a tab so the member knows where they are. */
.app-nav a {
  display: flex;
  align-items: center;
  height: var(--app-header-h);
  border-bottom: 2px solid transparent;
  color: var(--brand-ink);
  font-size: var(--t-body);
  font-weight: 600;
  text-decoration: none;
}

.app-nav a[aria-current="page"] {
  border-bottom-color: var(--brand-ink);
}

.app-identity {
  position: relative;
}

.app-identity-trigger {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--hit);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--brand-rule);
  background: var(--ground-sheet);
  color: var(--brand-ink);
  font: inherit;
  font-size: var(--t-small);
  cursor: pointer;
}

.app-identity-initial {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  background: var(--ground-ink);
  color: var(--brand-paper);
  font-family: var(--brand-display);
  font-size: 16px;
}

.app-identity-menu {
  position: absolute;
  top: calc(100% + var(--s-2));
  right: 0;
  z-index: 20;
  display: grid;
  min-width: 240px;
  border: 1px solid var(--brand-rule);
  background: var(--ground-sheet);
}

.app-identity-menu-head {
  display: grid;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--brand-rule);
}

.app-identity-menu a,
.app-identity-menu button {
  display: flex;
  align-items: center;
  min-height: var(--hit);
  padding: 0 var(--s-4);
  border: 0;
  border-top: 1px solid var(--brand-rule);
  background: none;
  color: var(--brand-ink);
  font: inherit;
  font-size: var(--t-body);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.app-identity-menu a:first-of-type {
  border-top: 0;
}

/* ⚠️ Legal links are quiet but present. There is no marketing footer in here to hold them. */
.app-identity-legal {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--brand-rule);
}

.app-identity-legal a {
  min-height: 0;
  padding: 0;
  border: 0;
  color: var(--brand-body-grey);
  font-size: var(--t-micro);
  text-decoration: underline;
}

/* ── Type roles ─────────────────────────────────────────────────────────────────────────────── */

.app h1 {
  margin: 0;
  font-size: var(--t-display);
  line-height: var(--t-display-lh);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.app h2 {
  margin: 0;
  font-size: var(--t-heading);
  line-height: var(--t-heading-lh);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.app p {
  margin: 0;
}

.app-lead {
  font-size: var(--t-lead);
  line-height: var(--t-lead-lh);
}

.app-small {
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
  color: var(--brand-body-grey);
}

.app-micro {
  font-size: var(--t-micro);
  line-height: var(--t-micro-lh);
  color: var(--brand-body-grey);
}

/* ⚠️ Silkscreen at 16 and 24 only, never a headline, never tracked. */
.app-label {
  font-family: var(--brand-display);
  font-size: 16px;
  line-height: 16px;
  color: var(--brand-body-muted);
}

.app-mono {
  font-family: var(--brand-mono);
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
  color: var(--brand-body-grey);
}

/* ── Frames: whose problem is it? ───────────────────────────────────────────────────────────── */

/* 🚨 The frame answers before the words do, and it comes from `fault`, never from matching copy. */
.app-panel {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-6);
  border: 1px solid var(--brand-rule);
  background: var(--ground-sheet);
}

/* The one thing to do on this screen. Enforced as one-per-screen by test. */
.app-panel-action {
  border: 2px solid var(--brand-ink);
}

/* At our end. Recessed and calm: not theirs to hold. */
.app-panel-ours {
  border: 1px dashed var(--brand-body-grey);
  background: var(--ground-sunken);
}

/* Theirs to fix. The only brick in the product. */
.app-panel-member {
  border: 2px solid var(--brand-base-lobes);
}

.app-panel-tag {
  justify-self: end;
  font-family: var(--brand-display);
  font-size: 16px;
  line-height: 16px;
}

.app-panel-ours .app-panel-tag {
  color: var(--brand-body-grey);
}

.app-panel-member .app-panel-tag {
  color: var(--brand-base-lobes);
}

/* ── StatusMark: a square that always ships with a word ─────────────────────────────────────── */

.app-mark {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  font-size: 12px;
  line-height: 1;
}

.app-mark-lg {
  width: 32px;
  height: 32px;
  font-size: 16px;
}

.app-mark-proven {
  background: var(--brand-calyx);
  color: var(--brand-paper);
}

.app-mark-handed {
  background: var(--brand-ink);
  color: var(--brand-paper);
}

.app-mark-attested {
  border: 1px solid var(--brand-ink);
  color: var(--brand-ink);
}

.app-mark-action {
  background: var(--brand-ember);
  color: var(--brand-ink);
}

.app-mark-progress {
  border: 1px solid var(--brand-ember);
  color: var(--brand-ember);
}

/* ⚠️ No glyph and no text colour: the future mark is an empty dashed square. The gate caught the
   text-colour version here within minutes of it being written. At 3.47:1 it is a line colour, and
   the word beside the mark is what carries the meaning anyway. */
.app-mark-future {
  border: 1px dashed var(--status-future-line);
}

.app-mark-ours {
  background: var(--brand-body-grey);
  color: var(--brand-paper);
}

.app-mark-unsure {
  border: 1px solid var(--status-unsure);
  background: var(--status-unsure-wash);
  color: var(--brand-ink);
}

.app-mark-paused {
  border: 1px solid var(--brand-body-grey);
  background: var(--ground-sunken);
  color: var(--brand-body-grey);
}

.app-mark-member {
  background: var(--brand-base-lobes);
  color: var(--brand-paper);
}

/* ⚠️ Ember, because it marks where you are — but no glyph and no "action" semantics, so the
   screen's single "Your turn" emphasis stays on the task. */
.app-mark-position {
  background: var(--brand-ember);
}

.app-mark-neutral {
  border: 1px solid var(--brand-body-grey);
  color: var(--brand-body-grey);
}

.app-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
  font-weight: 600;
}

/* ── SignalLine: Haba → your Gmail filter → the Haba label ──────────────────────────────────── */

.app-signal {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: start;
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-signal li {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-2);
  text-align: center;
}

/* 🚨 The middle node is permanently in a sunken band: Haba cannot see this part and never will.
   It is the one place the product explains its own limit without being asked. */
.app-signal-blind {
  background: var(--ground-sunken);
}

.app-signal-name {
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
  font-weight: 600;
}

.app-signal-sub {
  font-size: var(--t-micro);
  line-height: var(--t-micro-lh);
  color: var(--brand-body-grey);
}

.app-signal-blind-caption {
  font-size: var(--t-micro);
  line-height: var(--t-micro-lh);
  font-style: italic;
  color: var(--brand-body-grey);
}

/* ── JourneySteps ───────────────────────────────────────────────────────────────────────────── */

.app-journey {
  display: grid;
  gap: var(--s-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-journey li {
  display: grid;
  grid-template-columns: 24px 1fr;
  align-items: start;
  gap: var(--s-3);
}

.app-journey-title {
  font-size: var(--t-body);
  line-height: var(--t-body-lh);
  font-weight: 600;
}

.app-journey-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--brand-rule);
}

.app-journey-squares {
  display: flex;
  gap: var(--s-1);
}

.app-journey-square {
  width: 12px;
  height: 12px;
}

/* ⚠️ Filled for proven, outlined for attested. The progress row itself encodes how each step is
   known, so a member can see that we never verified their filter without being told. */
.app-journey-square-proven {
  background: var(--brand-calyx);
}

.app-journey-square-attested {
  border: 2px solid var(--brand-ink);
}

.app-journey-square-handed {
  background: var(--brand-ink);
}

.app-journey-square-future {
  border: 1px dashed var(--status-future-line);
}

/* The phone progress bar. */
.app-progress {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-1);
}

.app-progress span {
  height: 6px;
  background: var(--ground-sunken);
}

.app-progress .is-done {
  background: var(--brand-calyx);
}

.app-progress .is-attested {
  background: var(--brand-ink);
}

.app-progress .is-current {
  background: var(--brand-ember);
}

/* ── Notice ─────────────────────────────────────────────────────────────────────────────────── */

.app-notice {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
}

.app-notice-success {
  border: 1px solid var(--brand-calyx);
  background: var(--status-proven-wash);
}

.app-notice-warning {
  border: 1px solid var(--status-unsure);
  background: var(--status-unsure-wash);
}

.app-notice-ours {
  border: 1px dashed var(--brand-body-grey);
  background: var(--ground-sunken);
}

/* ── Actions ────────────────────────────────────────────────────────────────────────────────── */

/* ⚠️ Ink is the action; ember is reserved for signal and the copy control, so "press this" and
   "this is moving" never compete. There is no disabled-grey primary: an action that cannot succeed
   is absent, and the copy says why. */
.app-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
}

.app-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--hit-primary);
  padding: 0 var(--s-6);
  border: 1px solid var(--brand-ink);
  background: var(--brand-ink);
  color: var(--brand-paper);
  font: inherit;
  font-size: var(--t-body);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.app-button-secondary {
  background: var(--ground-sheet);
  color: var(--brand-ink);
}

.app-button-quiet {
  min-height: var(--hit);
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-ink);
  text-decoration: underline;
}

.app-button-copy {
  border-color: var(--brand-ember);
  background: var(--brand-ember);
  color: var(--brand-ink);
}

.app-button:focus-visible,
.app-identity-trigger:focus-visible,
.app-identity-menu a:focus-visible,
.app-identity-menu button:focus-visible,
.app-nav a:focus-visible,
.app-disclosure:focus-visible {
  outline: 2px solid var(--brand-ink);
  outline-offset: 2px;
}

.app-disclosure {
  min-height: var(--hit);
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-ink);
  font: inherit;
  font-size: var(--t-small);
  text-decoration: underline;
  cursor: pointer;
}

/* ── CriticalValue ──────────────────────────────────────────────────────────────────────────── */

/* 🚨 Promoted to ink so it is the darkest thing on the page. It rendered near-invisible once, on
   the one string a member must copy character for character. */
.app-critical {
  display: grid;
  gap: var(--s-2);
}

.app-critical-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0;
}

.app-critical-value {
  flex: 1 1 320px;
  min-width: 0;
  padding: var(--s-4);
  background: var(--ground-ink);
  color: var(--brand-paper);
  font-family: var(--brand-mono);
  font-size: var(--t-body);
  line-height: var(--t-body-lh);
  overflow-wrap: anywhere;
  user-select: all;
}

/* ── Home ───────────────────────────────────────────────────────────────────────────────────── */

.app-home {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  align-items: start;
  gap: var(--s-8);
}

.app-home-single {
  grid-template-columns: minmax(0, 1fr);
}

/* ⚠️ Setup inverts the proportions: the rail is a narrow margin note and the task owns the page.
   With the confirmed layout's `1fr 320px` the rail took the wide column and the one thing the
   member had to do was squeezed into 320px, where every line wrapped. */
.app-home-setup {
  grid-template-columns: 280px minmax(0, 1fr);
}

/* Each journey row stacks its title over how-it-is-known; they ran together on one line. */
.app-journey li > span {
  display: grid;
  gap: var(--s-1);
}

.app-aside {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-6);
  border: 1px solid var(--brand-rule);
  background: var(--ground-sheet);
}

/* ⚠️ Informational only. No switch styling, no action styling: these are not things to turn on. */
.app-limits {
  display: grid;
  gap: var(--s-3);
  margin-top: var(--s-12);
  padding-top: var(--s-4);
  border-top: 1px solid var(--brand-rule);
}

.app-limits ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-6);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--brand-body-grey);
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
}

/* ── Gmail phases ───────────────────────────────────────────────────────────────────────────── */

.app-phases {
  display: grid;
  gap: var(--s-6);
}

.app-phase {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: var(--s-3) var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--brand-rule);
}

.app-phase-n {
  font-family: var(--brand-display);
  font-size: 16px;
  line-height: 24px;
  color: var(--brand-ember);
}

.app-phase-steps {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--brand-body-grey);
  font-size: var(--t-small);
  line-height: var(--t-small-lh);
}

.app-phase-steps li {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: var(--s-2);
}

.app-phase-steps b {
  font-family: var(--brand-mono);
  font-weight: 500;
}

/* A durable schematic: plain shapes, never a screenshot that dates. */
.app-diagram {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  border: 1px solid var(--brand-rule);
  background: var(--ground-paper);
}

.app-diagram-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-micro);
  line-height: var(--t-micro-lh);
  color: var(--brand-body-grey);
}

.app-diagram-box {
  flex: 1 1 auto;
  padding: var(--s-2);
  border: 1px solid var(--brand-body-grey);
  background: var(--ground-sheet);
}

.app-diagram-focus {
  border: 2px solid var(--brand-ember);
}

/* ── Account ────────────────────────────────────────────────────────────────────────────────── */

.app-account {
  display: grid;
  gap: var(--s-8);
  max-width: 720px;
}

.app-account-section {
  display: grid;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--brand-rule);
}

.app-account-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

/* ── Motion ─────────────────────────────────────────────────────────────────────────────────── */

/* ⚠️ Motion explains state; it never decorates. Every animation below has a resting state that
   carries the same information, and `prefers-reduced-motion` removes all of it without loss. */
@keyframes app-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}

@keyframes app-travel {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(14px);
  }
}

@keyframes app-stamp {
  0% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}

.app-mark-progress {
  animation: app-pulse 1.1s ease-in-out infinite;
}

.app-signal-travel {
  animation: app-travel 1.4s steps(4) infinite alternate;
}

.app-stamped {
  animation: app-stamp 220ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .app-mark-progress,
  .app-signal-travel,
  .app-stamped {
    animation: none;
  }
}

/* Shown only on phones; the desktop rail carries the same model at a different density. */
.app-phone-only {
  display: none;
}

/* ── Phone ──────────────────────────────────────────────────────────────────────────────────── */

/* 🚨 A design, not a breakpoint. The display and title drop one step, the shell pads to 16, the
   two-column Home becomes one, the signal line stacks rather than squashing, and the primary
   action sticks to the bottom so it is always reachable. */
@media (max-width: 760px) {
  .app {
    --app-pad: 16px;
    --t-display: 32px;
    --t-display-lh: 36px;
    --t-title: 24px;
    --t-title-lh: 32px;
  }

  .app-main {
    padding: var(--s-6) var(--app-pad) var(--s-16);
  }

  .app-header {
    gap: var(--s-4);
  }

  .app-nav {
    gap: var(--s-4);
  }

  .app-home,
  .app-home-setup {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-phone-only {
    display: block;
  }

  /* ⚠️ The desktop rail is redundant on a phone, where the bar says the same thing in one line. */
  .app-home [data-testid="setup-rail"] {
    display: none;
  }

  .app-signal {
    grid-template-columns: 1fr;
  }

  /* ⚠️ The mark takes column one; every word takes column two. Without the explicit placement the
     sub-label and the blind caption flowed into the grid side by side and each wrapped to four
     narrow lines. */
  .app-signal li {
    grid-template-columns: 24px minmax(0, 1fr);
    justify-items: start;
    text-align: left;
  }

  .app-signal li > :not(.app-mark) {
    grid-column: 2;
  }

  .app-limits ul {
    flex-direction: column;
    gap: var(--s-2);
  }

  .app-phase {
    grid-template-columns: minmax(0, 1fr);
  }

  .app-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .app-sticky-action {
    position: sticky;
    bottom: 0;
    z-index: 10;
    margin: 0 calc(var(--app-pad) * -1) calc(var(--s-16) * -1);
    padding: var(--s-3) var(--app-pad) var(--s-4);
    border-top: 1px solid var(--brand-rule);
    background: var(--ground-paper);
  }

  .app-sticky-action .app-button {
    width: 100%;
  }
}
