/* ═══════════════════════════════════════════════════════════════════════════
   INK & ASH — shared stylesheet
   Locked identity, Aug 31 2026. Spec: docs/design/

   CANONICAL SOURCE: web/shared/ink.css
   web/public/ink.css and web/app/ink.css are generated copies — lifechief.ai
   and app.lifechief.ai are two separate Netlify sites publishing from two
   separate folders, so each deploy root needs its own copy of the file.
   Edit this file, then run:  python scripts/sync_web_css.py
   tests/test_web_assets.py fails the suite if the copies have drifted.

   Light is the default ground. Dark is a designed intention, not an inversion.
   Roughly four working colours on any one screen. Accent is a signal — CTA,
   key insight, moment of resolution — never decoration. State is never carried
   by hue alone: every coloured state also carries an icon and/or a label, so it
   survives a grayscale screenshot and colourblindness.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── ground ───────────────────────────────────────────────────────────── */
  --canvas:          #F1F2F0;   /* page ground */
  --canvas-alt:      #E6E8E6;   /* secondary bands, identity sheets */
  --surface:         #FFFFFF;   /* cards, ask box, sheets */
  --hairline:        #DEE1DF;   /* dividers, input borders */
  --hairline-strong: #D6D9D6;   /* card borders on canvas-alt */
  --hairline-soft:   #EDEFED;   /* row dividers inside a surface */
  --canvas-raise:    #F5F6F5;   /* tab bar, desktop nav rail — a half-step
                                   above the canvas, below the surface */

  /* ── signal ───────────────────────────────────────────────────────────── */
  --accent:          #2C3A52;   /* CTAs, mark centre point, resolution */
  --accent-deep:     #1B2536;   /* accent hover only */
  --attention:       #A8622F;   /* conflict, stranded change, stale source,
                                   errand confirm. Nowhere else. */

  /* ── ink & ash ────────────────────────────────────────────────────────── */
  --ink:             #1E2226;   /* body copy, headings, dark ground */
  --ash:             #8A9095;   /* secondary copy, Life in the wordmark */
  --ash-strong:      #4C5257;   /* the darkest ash — lead paragraph under a
                                   heading, and the consent-block label. One
                                   step up from --ash-mid, not a synonym for
                                   it: the A2P pages were binding this value
                                   to the --ash-mid name, which is why it gets
                                   an explicit token rather than a hex. */
  --ash-mid:         #565C60;   /* body copy on canvas */
  --ash-light:       #7C8285;   /* eyebrow labels */
  --ash-body:        #6B7176;   /* long-form body */
  --ash-faint:       #A0A5A8;   /* role captions */
  --ash-rule:        #C6CBCF;   /* heavy rules, big numerals */
  --ash-placeholder: #A9AFB3;   /* input placeholders, the or divider */

  /* ── dark ground (feature bands, footer, night theme) ─────────────────── */
  --ground:           #17191C;  /* marketing hero */
  --ground-panel:     #1E2226;  /* feature band, footer, night canvas */
  --ground-inset:     #24282C;  /* visual wells, night surface */
  --ink-on-dark:      #F1F2F0;
  --ash-on-dark:      #9AA0A4;
  --hairline-on-dark: #343A3F;
  --hairline-dark:    rgba(241,242,240,0.08);  /* hairline inside a dark band,
                                   where a flat colour would band against the
                                   inset wells sitting on top of it */
  --slate-on-dark:    #A8BAD6;  /* eyebrows + links on dark ground */

  /* ── consent block (carrier-reviewed surfaces) ────────────────────────── */
  --consent-bg:      #F5F6F5;
  --consent-line:    #E4E7E5;

  /* ── geometry ─────────────────────────────────────────────────────────── */
  --r-sm:   4px;   /* cards, panels, inputs, buttons */
  --r-md:   8px;   /* nested surfaces */
  --r-lg:  10px;   /* standalone sheets */
  --r-tile: 14px;  /* avatars, home-screen tile */
}

/* Night theme. Opt-in via <html data-theme="night"> — set from Control Panel,
   Appearance, never from a top-bar toggle. Only the ground and ink swap; accent
   and attention are the same signals in both themes. */
[data-theme="night"] {
  --canvas:          #1E2226;
  --canvas-alt:      #1A1E22;
  --surface:         #252A2E;
  --hairline:        #343A3F;
  --hairline-strong: #3D454F;
  --hairline-soft:   #2C3236;
  --canvas-raise:    #22272B;
  --ink:             #F1F2F0;
  --ash:             #9AA0A4;
  --ash-mid:         #9AA0A4;
  --ash-light:       #868C90;
  --ash-body:        #9AA0A4;
  --ash-faint:       #7A8084;
  --ash-strong:      #C8CDD0;
  --ash-rule:        #4C5257;
  --ash-placeholder: #767C80;
  --consent-bg:      #22272B;
  --consent-line:    #343A3F;
}

/* ── reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--canvas);
  color: var(--ink);
  font-family: 'Tenor Sans', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

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

/* ── type scale ─────────────────────────────────────────────────────────── */
/* Cormorant Garamond italic 300 is display and emotional moments only:
   greetings, brand statements, empty states. Large and sparing —
   MAXIMUM ONE Cormorant moment per screen, and never in the logo. */
.display, .greeting {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-weight: 300;
  color: var(--ink);
}
.display  { font-size: 42px; line-height: 1.15; }
.greeting { font-size: 34px; line-height: 1.1; }

.eyebrow {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ash-light);
}

.body    { font-size: 15px; line-height: 1.65; color: var(--ash-mid); }
.body-sm { font-size: 13px; line-height: 1.6;  color: var(--ash-body); }

/* ── wordmark ───────────────────────────────────────────────────────────── */
/* Life in ash, Chief in ink, all Tenor Sans, sentence case. Bodoni is retired
   from the identity entirely, and Cormorant never appears in the logo. */
.wordmark        { font-size: 19px; line-height: 1; letter-spacing: 0.02em; white-space: nowrap; }
.wordmark .life  { color: var(--ash); }
.wordmark .chief { color: var(--ink); }
.wordmark-xl { font-size: 54px; }
.wordmark-l  { font-size: 31px; }
.wordmark-s  { font-size: 13px; letter-spacing: 0.03em; }

.on-dark .wordmark .life,  .wordmark-on-dark .life  { color: #79808A; }
.on-dark .wordmark .chief, .wordmark-on-dark .chief { color: var(--ink-on-dark); }

/* Lockup: mark at 1.3x the type size, gap at 0.45x the mark. Optical, so
   expect a nudge. Clear space around the mark equals the diameter of the
   centre point; fragments touching a container edge read as damage. */
.lockup { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.lockup:hover { color: inherit; }

/* The mark's parts, so one inline asset serves both grounds. Three assets by
   size, never one scaled SVG: full mark at 40px and up, middle ring dropped
   below 36px, fragments and a solid point at 24px and under. The dash pattern
   is a fixed authored value — computing it turns the fragments into a dashed
   border. The mark never animates. */
.mark-frag { stroke: var(--ash); }
.mark-ring { stroke: #79808A; }
.mark-core { fill: var(--accent); }
[data-theme="night"] .mark-frag { stroke: #4E586A; }
[data-theme="night"] .mark-core { fill: var(--ink-on-dark); }

/* ── chrome ─────────────────────────────────────────────────────────────── */
nav.ink {
  padding: 20px 56px;
  border-bottom: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
nav.ink .navlink {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ash-light); text-decoration: none;
}
nav.ink .navlink:hover { color: var(--ink); }

/* ── surfaces ───────────────────────────────────────────────────────────── */
/* Elevation is essentially none. Separation is by hairline and value,
   never by shadow. */
.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: 38px 34px;
}
.sheet {
  background: var(--canvas);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-lg);
}
.panel {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
}
.rule { height: 1px; background: #DDE0DD; border: 0; }

/* Hairline grid — a 1px-gap grid on a hairline ground, so the dividers are
   the background showing through. */
.hairgrid { display: grid; gap: 1px; background: var(--hairline); }
.hairgrid > * { background: var(--canvas); }

/* Row set inside a panel: dividers between, none after the last. */
.rowset { display: flex; flex-direction: column; }
.rowset > .row {
  padding: 15px 18px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border-bottom: 1px solid var(--hairline-soft);
}
.rowset > .row:last-child { border-bottom: none; }
.row-label { font-size: 15px; color: var(--ash-mid); }
.row-value { font-size: 15px; color: var(--ink); }

/* ── forms ──────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 7px; }
.label {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ash);
}
.label .optional { text-transform: none; letter-spacing: 0.02em; color: var(--ash-placeholder); }

.input {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 5px;
  padding: 14px;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 17px;
  color: var(--ink);
  width: 100%;
  -webkit-appearance: none;
}
.input:focus { outline: none; border-color: var(--accent); }
.input::placeholder { color: var(--ash-placeholder); }
/* Invalid carries the attention colour AND a message — never colour alone. */
.input.invalid { border-color: var(--attention); }
.field-error { display: none; font-size: 13px; line-height: 1.5; color: var(--attention); }
.field-error.visible { display: block; }

.btn {
  background: var(--accent);
  color: var(--ink-on-dark);
  border: none;
  border-radius: 5px;
  width: 100%;
  padding: 15px;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 16px;
  letter-spacing: 0.02em;
  text-align: center;
  cursor: pointer;
  display: block;
  text-decoration: none;
}
.btn:hover    { background: var(--accent-deep); color: var(--ink-on-dark); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* Secondary action on a surface — Google/Apple, Connect. */
.btn-quiet {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--hairline);
  border-radius: 5px;
  width: 100%;
  padding: 14px;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 16px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 11px;
  text-decoration: none;
}
.btn-quiet:hover { border-color: var(--hairline-strong); color: var(--ink); }

/* Skip must be visible, not hidden in a corner — a carrier reviewer will
   click it, and if that path errors the registration fails on it. */
.btn-text {
  background: none; border: none;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 15px; color: var(--accent);
  cursor: pointer; text-align: center; width: 100%;
  padding: 0; text-decoration: none; display: block;
}
.btn-text:hover { color: var(--accent-deep); }
.btn-text.muted { color: var(--ash); }

.or { display: flex; align-items: center; gap: 14px; }
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--hairline); }
.or span {
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ash-placeholder);
}

/* ── consent block — CARRIER REVIEWED, DO NOT REWORD ────────────────────── */
/* Consent is offered, never assumed. The box is not pre-checked and is not
   required to submit; unchecked must look completely normal, not like an
   error. The text is byte-identical on every surface that carries it — a
   reviewer comparing them must find no variation. */
.consent {
  background: var(--consent-bg);
  border: 1px solid var(--consent-line);
  border-radius: 6px;
  padding: 20px;
  display: flex; gap: 15px;
}
.consent input[type="checkbox"] {
  width: 23px; height: 23px; flex: none;
  accent-color: var(--accent);
  margin: 0; cursor: pointer;
}
.consent label { font-size: 14px; line-height: 1.6; color: var(--ash-mid); cursor: pointer; }
.not-required { font-size: 13px; line-height: 1.55; color: var(--ash-light); text-align: center; }
.fine-print   { font-size: 13px; line-height: 1.6;  color: var(--ash-body); }

/* Quiet informational note — nothing is sent to anyone. */
.note {
  background: var(--consent-bg);
  border: 1px solid var(--consent-line);
  border-radius: 6px;
  padding: 16px;
  display: flex; gap: 13px;
  font-size: 14px; line-height: 1.6; color: var(--ash-mid);
}
.note svg { flex: none; margin-top: 1px; }

/* ── chips ──────────────────────────────────────────────────────────────── */
/* Person chips are fully round — every commitment names one person. */
.chip-person {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--hairline);
  border-radius: 100px;
  padding: 4px 12px 4px 5px;
  font-size: 13px; color: var(--ink);
  white-space: nowrap;
}
.chip-person .initial {
  width: 21px; height: 21px; border-radius: 11px; flex: none;
  background: #E1E4E2; color: #4C5257;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px;
}
[data-theme="night"] .chip-person .initial { background: #343A3F; color: #C8CDD0; }
.chip {
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  padding: 8px 14px;
  font-size: 13px; color: var(--ash-mid);
  background: var(--surface);
  white-space: nowrap;
  cursor: pointer;
  font-family: 'Tenor Sans', sans-serif;
}
.chip:hover { border-color: var(--hairline-strong); color: var(--ink); }

.avatar {
  width: 34px; height: 34px; border-radius: 17px;
  background: #E1E4E2; color: #4C5257;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; flex: none;
}

/* Horizontally scrollable rail, no visible scrollbar. */
.rail {
  display: flex; gap: 9px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.rail::-webkit-scrollbar { display: none; }

/* ── app shell — app.lifechief.ai ───────────────────────────────────────── */
/* Five destinations: Home · Reminders · Calendar · Network · Control Panel.
   Bottom tab bar on mobile, left rail from 1024px. LABELS ARE ALWAYS VISIBLE
   — no icon-only nav, this product has grandparents on it. The top bar is
   mark + wordmark left, avatar right, and nothing else: there is no theme
   toggle up there, because Appearance lives in Control Panel. */

.app { display: flex; flex-direction: column; min-height: 100dvh; }

.app-top {
  position: sticky; top: 0; z-index: 20;
  background: var(--canvas);
  border-bottom: 1px solid var(--hairline);
  padding: 16px 20px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.app-top .wordmark { font-size: 17px; }

.app-main { flex: 1; min-width: 0; padding-bottom: calc(80px + env(safe-area-inset-bottom)); }

.screen { display: none; }
.screen.on { display: block; }

.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--canvas-raise);
  border-top: 1px solid var(--hairline);
  padding: 11px 8px calc(13px + env(safe-area-inset-bottom));
  display: flex;
}
.tab {
  flex: 1; min-width: 0;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: 'Tenor Sans', sans-serif; font-size: 11px;
  color: var(--ash);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.tab svg { display: block; }
.tab.on { color: var(--accent); }

/* Desktop: the rail replaces the tab bar and carries the lockup and the user,
   so the top bar is dropped rather than stacked on top of it. */
.siderail { display: none; }
.siderail-top { display: flex; flex-direction: column; gap: 34px; }
.siderail .lockup   { padding: 0 24px; }
.siderail .wordmark { font-size: 18px; }
.railnav { display: flex; flex-direction: column; }
.railtab {
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-left: 2px solid transparent;
  font-family: 'Tenor Sans', sans-serif; font-size: 15px;
  color: var(--ash-strong);
  display: flex; align-items: center; gap: 13px;
  padding: 13px 24px 13px 26px;
}
.railtab:hover { color: var(--ink); }
.railtab .railtab-n { margin-left: auto; font-size: 13px; color: var(--ash); }
.railtab.on {
  background: var(--surface);
  border-left-color: var(--accent);
  color: var(--accent);
  padding-left: 24px;
}
.railuser { display: flex; align-items: center; gap: 12px; padding: 0 24px; }
.railuser .avatar { width: 32px; height: 32px; border-radius: 16px; }
.railuser span { font-size: 14px; color: var(--ash-strong); }

@media (min-width: 1024px) {
  .app      { flex-direction: row; }
  .app-top  { display: none; }
  .tabbar   { display: none; }
  .app-main { padding-bottom: 0; }
  .siderail {
    display: flex; flex-direction: column; justify-content: space-between;
    flex: 0 0 232px;
    position: sticky; top: 0; height: 100dvh;
    background: var(--canvas-raise);
    border-right: 1px solid var(--hairline);
    padding: 26px 0;
  }
}

/* ── the three-tier answer ──────────────────────────────────────────────── */
/* Chief narrates in one short line; the DATA lives in a bordered card; an
   action chip closes the turn. Never dump a list into a chat bubble — the
   text narrates, the card is the truth. */
.datacard {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.datacard > * { border-bottom: 1px solid var(--hairline-soft); }
.datacard > :last-child { border-bottom: 0; }
.dhead {
  padding: 13px 16px;
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ash);
}
.drow {
  padding: 14px 16px;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.drow-main  { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drow-when  { font-size: 13px; color: var(--ash); }
.drow-title { font-size: 15px; line-height: 1.45; color: var(--ink); }
.drow-meta  { font-size: 13px; line-height: 1.5; color: var(--ash-body); }
.drow-side  { flex: none; display: flex; align-items: center; gap: 8px; }

/* Loading is not a spinner. The mark never animates — Chief has already
   handled it, so the identity does not perform the handling. A static
   fragment glyph, and a line that names what is being read. */
.thinking { display: flex; align-items: center; gap: 11px; }
.thinking span { font-size: 14px; color: var(--ash-faint); }

/* ── tappable pills ─────────────────────────────────────────────────────── */
/* Fully round — the same family as the person chip. .chip (4px) stays the
   square metadata tag; these are the ones a thumb lands on. */
.chip-pill {
  border: 1px solid var(--hairline-strong);
  background: none;
  border-radius: 100px;
  padding: 9px 15px;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 14px; color: var(--ash-strong);
  white-space: nowrap; cursor: pointer;
}
.chip-pill:hover { border-color: var(--ash); color: var(--ink); }
.chip-accent {
  border: 1px solid var(--accent);
  background: var(--accent);
  border-radius: 100px;
  padding: 10px 18px;
  font-family: 'Tenor Sans', sans-serif;
  font-size: 14px; color: var(--ink-on-dark);
  white-space: nowrap; cursor: pointer;
}
.chip-accent:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

/* ── parked ─────────────────────────────────────────────────────────────── */
/* Unbuilt things get parked, not hidden. A control that looks live and does
   nothing is worse than one that says so, and the "soon" line holds the
   baseline so the layout does not move when the feature ships. Google/Apple
   sign-in and the Home mic both wear this. */
.parked { opacity: 0.5; pointer-events: none; }
.parked-note {
  font-size: 12px; letter-spacing: 0.02em;
  color: var(--ash-placeholder); text-align: center;
}

/* ── progress ───────────────────────────────────────────────────────────── */
/* Step count is honest: five steps, stated up front, bar filled to match.
   If a step is skipped the bar still completes — a partial finish would
   read as a failure state. */
.progress { display: flex; gap: 7px; }
.progress span { height: 3px; flex: 1; background: var(--hairline); border-radius: 2px; }
.progress span.on { background: var(--accent); }
.step-count { font-size: 13px; color: var(--ash-body); }

/* ── attention ──────────────────────────────────────────────────────────── */
/* Four sanctioned uses only: calendar conflict, stranded change, stale
   source, errand confirm. Always with an icon AND the literal word. */
.attn { color: var(--attention); }
.attn-badge {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--attention);
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase;
}

/* ── footer ─────────────────────────────────────────────────────────────── */
footer.ink {
  background: var(--ground-panel);
  padding: 40px 56px;
  display: flex; flex-wrap: wrap; gap: 28px;
  justify-content: space-between; align-items: flex-start;
}
footer.ink .wordmark { font-size: 16px; }
footer.ink .wordmark .life  { color: #5C6266; }
footer.ink .wordmark .chief { color: rgba(241,242,240,0.6); }
.foot-block  { display: flex; flex-direction: column; gap: 12px; max-width: 380px; }
.foot-entity { font-size: 13px; line-height: 1.6; color: rgba(241,242,240,0.45); }
.foot-links  { display: flex; gap: 24px; flex-wrap: wrap; }
.foot-link {
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(241,242,240,0.3); text-decoration: none;
}
.foot-link:hover { color: var(--ink-on-dark); }
.foot-sms { font-size: 12px; line-height: 1.65; color: rgba(241,242,240,0.35); max-width: 420px; }

/* ── utilities ──────────────────────────────────────────────────────────── */
.stack  { display: flex; flex-direction: column; }
.center { text-align: center; }
.hidden { display: none !important; }
.pretty { text-wrap: pretty; }

/* ── responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  nav.ink    { padding: 18px 24px; }
  footer.ink { padding: 32px 24px; }
  .card      { padding: 30px 24px; }
  .display   { font-size: 34px; }
  .greeting  { font-size: 30px; }
}

/* The mark never animates. No loading spinner built from the fragments — it is
   the obvious loading state and it contradicts the voice. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
