/* ============================================================================
   LUCID COMPONENTS — the shapes the tokens make.

   Requires lucid.tokens.css. Every value here reads a token; there are no raw
   colors, corners or shadows in this file, which is the rule the whole system
   rests on.

   This is not a UI kit and it is not trying to be. It is the small set of
   marks that make a thing recognizably Lucid — the signature, the atmosphere,
   the opening cadence, and the two controls. Everything else is free.
   ========================================================================= */

/* ── FOUNDATION ─────────────────────────────────────────────────────────── */

.lucid {
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  color: var(--text-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.lucid-measure {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--s-5);
}

.lucid-section {
  padding-block: var(--section-y);
}

/* A paragraph never runs wider than this, no matter how wide the screen is.
   Past about 68 characters the eye loses the start of the next line. */
.lucid-prose {
  max-width: var(--measure-text);
  text-wrap: pretty;
}

/* ══ THE SIGNATURE ═══════════════════════════════════════════════════════════
   THE SPINE.

   A bar on the leading edge of a surface. Its COLOR says who owns that step,
   and that is the whole idea: Lucid's business is drawing the line between
   the work a machine should do and the work a person should keep, so the
   brand's one signature mark carries exactly that information.

       signal (orange)  the system runs this, unattended
       ink    (black)   a person touches this
       clay   (brown)   this feeds back into the system

   It is the same mark at every scale and in every medium — a 3px rule down a
   card, a 6px rail down the side of a slide, a left border in an email, a
   lane marker in a workflow diagram, the live edge of a dashboard tile.

   Rules:
   - A spine always means ownership. Never use it as decoration, and never
     put one on a surface where the question "who runs this?" is meaningless.
   - Any view using spines carries the legend (.lucid-legend) at least once,
     so the colors are never left to be guessed.
   - Never introduce a fourth spine color. Three states is the point.
   ═════════════════════════════════════════════════════════════════════════ */

.lucid-spine {
  position: relative;
  padding-left: var(--s-5);
}

.lucid-spine::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: var(--r-mark);
  background: var(--spine-color, var(--signal));
}

/* The three states. */
.lucid-spine--system { --spine-color: var(--signal); }
.lucid-spine--person { --spine-color: var(--ink); }
.lucid-spine--loop   { --spine-color: var(--clay); }

/* The heavier rail, for a slide edge, a section marker, or a hero. Same mark,
   more of it — never a different mark. */
.lucid-spine--rail { padding-left: var(--s-6); }
.lucid-spine--rail::before { width: 6px; }

/* A spine set INSIDE a surface's padding rather than on its edge, for cards
   that already have their own inset. */
.lucid-spine--inset::before { left: var(--s-5); }

/* The legend. Any view that uses spines must show this once. */
.lucid-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.04em;
  color: var(--text-3);
}

.lucid-legend__item {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
}

.lucid-legend__key {
  width: 10px;
  height: 10px;
  border-radius: var(--r-mark);
  background: var(--spine-color, var(--signal));
  flex: none;
}

/* ══ THE ATMOSPHERE ══════════════════════════════════════════════════════════
   AURORA.

   One soft bloom of signal, low and wide, sitting behind the content on warm
   paper. It is what stops a light page reading as a blank document.

   Rules:
   - ONE bloom per view. A second one turns atmosphere into weather.
   - It is a radial bloom, never a linear gradient sweep across the page, and
     never purple. A purple-to-blue gradient on white is the single most
     common tell of a generated design.
   - It never sits over text it would tint. Keep it behind, and keep it faint.
   - **NEVER put this class on <body> or <html>.** Those two elements hand
     their overflow to the viewport instead of clipping their own contents, so
     the `overflow: clip` under this rule silently stops working and the bloom
     pushes the page sideways by its own width. Measured on a phone: a 62rem
     bloom on <body> made a 390px page 1,187px wide, and no element reported as
     overflowing because a pseudo-element is invisible to a DOM sweep. Put it
     on a wrapper div inside <body>; check-mobile-fit.mjs catches it either way.
   ═════════════════════════════════════════════════════════════════════════ */

.lucid-aurora {
  position: relative;
  isolation: isolate;
  overflow: clip;
}

.lucid-aurora::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset-inline-start: var(--aurora-x, 55%);
  inset-block-start: var(--aurora-y, -25%);
  width: var(--aurora-size, 70rem);
  aspect-ratio: 1;
  border-radius: var(--r-pill);
  background: radial-gradient(
    circle at center,
    var(--signal-glow) 0%,
    var(--signal-wash) 38%,
    transparent 68%
  );
  pointer-events: none;
}

/* The grain that keeps a large flat area of paper from looking like a screen
   fill. Faint enough to be felt rather than seen. */
.lucid-grain::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.4;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
}

/* ══ THE CONNECTIVE TISSUE ═══════════════════════════════════════════════════
   FILAMENT.

   A hairline curve in signal, joining two surfaces, optionally carrying a
   traveling dot. Used anywhere flow has to be shown: a workflow diagram, a
   hero graph, an architecture drawing, a pipeline on a slide.

   The traveling dot is the ONLY looping motion the brand allows, and it must
   stop when it is off screen (lucid.reveal.js handles that). Everything else
   moves once, in response to the reader.
   ═════════════════════════════════════════════════════════════════════════ */

.lucid-filament {
  fill: none;
  stroke: var(--signal);
  stroke-width: 1.25;
  opacity: 0.55;
  stroke-linecap: round;
}

.lucid-filament--loop {
  stroke: var(--clay);
  stroke-dasharray: 4 5;
  opacity: 0.5;
}

.lucid-packet {
  fill: var(--signal);
  r: 3;
  filter: drop-shadow(0 0 6px var(--signal-glow));
}

/* ══ THE OPENING CADENCE ═════════════════════════════════════════════════════
   Every Lucid asset — a page section, a slide, a proposal chapter, a diagram
   header — opens the same way and in this order:

       eyebrow  →  title  →  deck

   The eyebrow is mono, uppercase and widely tracked; it names WHERE the
   reader is. The title carries exactly one serif-italic phrase. The deck is
   one or two sentences and then it stops. That fixed cadence is most of what
   makes separate assets read as one company.
   ═════════════════════════════════════════════════════════════════════════ */

.lucid-eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: var(--w-medium);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  color: var(--signal);
  margin-bottom: var(--s-4);
}

.lucid-eyebrow--quiet { color: var(--text-3); }

.lucid-display,
.lucid-title {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  color: var(--text-1);
  text-wrap: balance;
}

.lucid-display {
  font-size: var(--t-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
}

.lucid-title {
  font-size: var(--t-title);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-title);
}

.lucid-heading {
  font-family: var(--font-display);
  font-size: var(--t-heading);
  font-weight: var(--w-bold);
  line-height: 1.25;
  letter-spacing: var(--ls-title);
  color: var(--text-1);
  text-wrap: balance;
}

/* THE EMPHASIS. Instrument Serif, italic, in signal.

   Exactly ONE phrase per view wears this, and it is the phrase that carries
   the meaning of the whole view — the words a person would lean on if they
   read the line out loud. Used twice on one screen it stops being emphasis
   and becomes a font choice. check-brand.mjs fails a page that uses it more
   than once in a single view. */
.lucid-emphasis {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: var(--w-regular);
  color: var(--signal);
  letter-spacing: 0;
  /* The serif's lowercase runs smaller than the sans at the same size, so it
     is nudged up to sit on the same optical line. */
  font-size: 1.06em;
}

.lucid-deck {
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--text-2);
  max-width: var(--measure-text);
  text-wrap: pretty;
}

/* Every number a reader might compare against another number is set in mono,
   so digits line up in a column and a figure never reflows as it updates.

   Never let a monospaced font run across the thousands separator of a money
   figure — the comma gets a full character cell and the number breaks apart.
   Set the separator in the body face, or use tabular-nums on the sans. */
.lucid-figure {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--w-medium);
  color: var(--text-1);
  letter-spacing: -0.01em;
}

/* ══ SURFACES ════════════════════════════════════════════════════════════════ */

.lucid-surface {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-surface);
  box-shadow: var(--e-raised);
  padding: var(--s-5);
}

.lucid-surface--flush {
  background: var(--shelf);
  box-shadow: none;
}

.lucid-surface--float {
  box-shadow: var(--e-floating);
}

/* The mono strip: a one-line note, a setup step, a command, a definition.
   Reads as something the system said rather than something marketing wrote. */
.lucid-strip {
  font-family: var(--font-mono);
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--text-2);
  background: var(--shelf);
  border: 1px solid var(--rule);
  border-radius: var(--r-control);
  padding: var(--s-3) var(--s-4);
  overflow-x: auto;
  /* Keeps written line breaks, and still wraps rather than pushing a phone
     screen sideways. Without this, a four-line snippet silently reflows into
     one run-on paragraph and stops being readable as code. */
  white-space: pre-wrap;
}

/* ══ CONTROLS ════════════════════════════════════════════════════════════════
   Two buttons and nothing else. A third button style is how a page stops
   having a primary action.                                                  */

.lucid-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-body);
  font-size: var(--t-body);
  font-weight: var(--w-semibold);
  letter-spacing: -0.01em;
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-control);
  border: 1px solid transparent;
  cursor: pointer;
  transition:
    background-color var(--d-state) var(--ease),
    border-color var(--d-state) var(--ease),
    transform var(--d-response) var(--ease),
    box-shadow var(--d-response) var(--ease);
}

.lucid-btn--primary {
  background: var(--signal);
  color: #ffffff;
  box-shadow: var(--e-signal);
}

@media (hover: hover) {
  .lucid-btn--primary:hover {
    background: var(--signal-press);
    transform: translate3d(0, calc(-1 * var(--lift)), 0);
  }
  .lucid-btn--secondary:hover {
    border-color: var(--rule-strong);
    background: var(--shelf);
  }
}

.lucid-btn--secondary {
  background: transparent;
  color: var(--text-1);
  border-color: var(--rule);
}

/* A keyboard reader must always be able to see where they are. This is not
   negotiable and it is not a style choice. */
.lucid-btn:focus-visible,
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
  border-radius: var(--r-control);
}

/* ══ DIAGRAM PARTS ═══════════════════════════════════════════════════════════
   Lucid draws a lot of workflows. These are the node shapes, so two diagrams
   drawn months apart still look like the same hand made them.               */

.lucid-node {
  display: inline-flex;
  flex-direction: column;
  gap: var(--s-1);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-surface);
  box-shadow: var(--e-raised);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small);
  color: var(--text-1);
}

/* The terminal node — where a flow starts or ends. Solid ink, full pill. */
.lucid-node--terminal {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
  border-radius: var(--r-pill);
  padding: var(--s-3) var(--s-6);
  align-items: center;
}

/* The reasoning node — where the model decides something. The one dark
   surface in a light diagram, so the eye lands on it first. */
.lucid-node--reason {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
  box-shadow: var(--e-floating), 0 0 0 4px var(--signal-wash);
}

.lucid-node__meta {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.06em;
  color: var(--text-3);
}

.lucid-node--terminal .lucid-node__meta,
.lucid-node--reason .lucid-node__meta {
  color: var(--signal-lift);
}

/* ══ RESPONSIVE FLOOR ════════════════════════════════════════════════════════
   Nothing in this system is allowed to push a phone screen sideways.        */

@media (max-width: 640px) {
  .lucid-measure { padding-inline: var(--s-4); }
  .lucid-spine   { padding-left: var(--s-4); }
  .lucid-spine--rail { padding-left: var(--s-5); }
}
