/* ═══════════════════════════════════════════════════════════════
   LL DESIGN SYSTEM — BASE + COMPONENTS
   Requires tokens.css. Framework-independent: works with plain
   HTML, with Tailwind, or inside a React/Astro component.
   ═══════════════════════════════════════════════════════════════ */

/* ───────────────────────────────────────────────────────────────
   BASE
   ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

/* Anchor targets clear the fixed header, plus a step of air */
[id] { scroll-margin-top: calc(var(--header-h) + var(--s-md)); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg-body);
  font-family: var(--font);
  font-size: var(--t-body);
  font-weight: var(--w-reg);
  line-height: var(--lh-loose);
  letter-spacing: var(--ls-normal);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; height: auto; }

/* Every corner is square. Overrides any framework default. */
*, input, select, textarea, button { border-radius: var(--radius); }

::selection { background: var(--signal); color: var(--fg-on-signal); }

:focus-visible {
  outline: var(--rule-w-heavy) solid var(--signal);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ───────────────────────────────────────────────────────────────
   TYPE
   No uppercase anywhere. Hierarchy comes from size / weight /
   color / rules — not from a second typeface.
   ─────────────────────────────────────────────────────────────── */
.t-display {
  font-size: var(--t-display); font-weight: var(--w-bold);
  line-height: var(--lh-tight); letter-spacing: var(--ls-display);
  color: var(--fg); margin: 0;
}
.t-h1 {
  font-size: var(--t-h1); font-weight: var(--w-bold);
  line-height: 1.15; letter-spacing: var(--ls-head);
  color: var(--fg); margin: 0;
}
.t-h2 {
  font-size: var(--t-h2); font-weight: var(--w-med);
  line-height: 1.25; letter-spacing: -0.01em;
  color: var(--fg); margin: 0;
}
.t-h3 {
  font-size: var(--t-h3); font-weight: var(--w-med);
  line-height: var(--lh-normal); color: var(--fg); margin: 0;
}
.t-lead   { font-size: var(--t-body-lg); line-height: var(--lh-loose); color: var(--fg-body); margin: 0; }
.t-body   { font-size: var(--t-body);    line-height: var(--lh-loose); color: var(--fg-body); margin: 0; }
.t-small  { font-size: var(--t-body-sm); line-height: var(--lh-normal); color: var(--fg-muted); margin: 0; }

/* Label = the old "technical drafting notation", now lowercase +
   tracked instead of uppercase. Mono carries the technical read. */
.t-label {
  font-size: var(--t-label); font-weight: var(--w-med);
  line-height: var(--lh-snug); letter-spacing: var(--ls-label);
  color: var(--fg-muted);
}
.t-micro {
  font-size: var(--t-micro); font-weight: var(--w-reg);
  line-height: var(--lh-snug); letter-spacing: var(--ls-micro);
  color: var(--fg-dim);
}
.t-signal { color: var(--fg-signal); }
.t-strong { color: var(--fg); }
.t-num    { font-variant-numeric: tabular-nums; }

a { color: inherit; text-decoration: none; }
.link {
  color: var(--fg-body);
  border-bottom: var(--rule-w) solid var(--rule);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.link:hover { color: var(--fg-signal); border-bottom-color: var(--signal); }

/* ───────────────────────────────────────────────────────────────
   LAYOUT
   ─────────────────────────────────────────────────────────────── */
.wrap {
  width: 100%; max-width: var(--maxw); margin-inline: auto;
  padding-inline: var(--margin-sm);
}
@media (min-width: 768px) { .wrap { padding-inline: var(--margin); } }

.section      { padding-block: var(--s-xl); }
.section--tight { padding-block: var(--s-lg); }
.section--sunken { background: var(--bg-sunken); }

.rule { width: 100%; height: var(--rule-w); background: var(--rule); border: 0; margin: 0; }
.rule--v { width: var(--rule-w); height: auto; align-self: stretch; }
.rule--active { background: var(--rule-active); }

.grid { display: grid; gap: var(--s-md); }
.grid--2 { grid-template-columns: 1fr; }
.grid--3 { grid-template-columns: 1fr; }
.grid--4 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); gap: var(--s-lg); }
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* Let one item claim two columns. Desktop only — grids are single-column
   on mobile, where spanning 2 would overflow the track. */
@media (min-width: 768px) { .span-2 { grid-column: span 2; } }

/* Blueprint grid backdrop — put on any section with position:relative */
.grid-bg { position: relative; }
.grid-bg::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  opacity: var(--grid-opacity);
  background-image:
    linear-gradient(var(--paper) 1px, transparent 1px),
    linear-gradient(90deg, var(--paper) 1px, transparent 1px);
  background-size: var(--grid-size) var(--grid-size);
}

/* ───────────────────────────────────────────────────────────────
   EYEBROW — section marker: dash + label
   ─────────────────────────────────────────────────────────────── */
.eyebrow {
  display: flex; align-items: center; gap: var(--s-sm);
  font-size: var(--t-label); font-weight: var(--w-med);
  letter-spacing: var(--ls-label); color: var(--fg-signal);
  margin-bottom: var(--s-md);
}
.eyebrow::before {
  content: ''; width: 1rem; height: var(--rule-w);
  background: var(--signal); flex-shrink: 0;
}
.eyebrow--muted { color: var(--fg-muted); }
.eyebrow--muted::before { background: var(--rule-hi); }

/* Live dot — the "functional indicator" */
.dot {
  width: 0.5rem; height: 0.5rem; background: var(--signal); flex-shrink: 0;
  animation: pulse 2s infinite;
}
.dot--idle  { background: transparent; border: var(--rule-w) solid var(--rule-hi); animation: none; }
.dot--muted { background: var(--fg-dim); animation: none; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }

/* ───────────────────────────────────────────────────────────────
   BUTTONS — the offset ghost-outline behaviour
   ─────────────────────────────────────────────────────────────── */
/* Paint order matters here. A negative-z-index pseudo-element paints ABOVE
   its own parent's background, so the fill cannot live on .btn itself or the
   ghost outline shows through the yellow. Instead: .btn is transparent and
   isolated, ::before draws the ghost, ::after draws the opaque fill over it.
   Equal z-index means tree order decides — ghost under fill. */
.btn {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-xs);
  padding: 0.8125rem 1.625rem;
  font-family: var(--font);
  font-size: var(--t-body-sm); font-weight: var(--w-med);
  letter-spacing: var(--ls-label);
  color: var(--fg-on-signal); background: transparent;
  border: 0; cursor: pointer; white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease);
}
.btn::before {                                  /* ghost outline — behind */
  content: ''; position: absolute; inset: 0; z-index: -1;
  border: var(--rule-w) solid var(--rule-active);
  transform: translate(var(--offset), var(--offset));
  transition: transform var(--dur-fast) var(--ease);
}
.btn::after {                                   /* opaque fill — in front  */
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--signal);
}
.btn:hover          { transform: translate(-3px, -3px); }
.btn:hover::before  { transform: translate(7px, 7px); }
.btn:active         { transform: translate(0, 0); }
.btn:active::before { transform: translate(var(--offset), var(--offset)); }

.btn--ghost {
  color: var(--fg); background: transparent;
  border: var(--rule-w) solid var(--rule-hi);
  padding: 0.75rem 1.5625rem;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.btn--ghost::before, .btn--ghost::after { content: none; }
.btn--ghost:hover  { transform: none; border-color: var(--signal); color: var(--fg-signal); }

.btn--sm    { padding: 0.5625rem 1.125rem; font-size: var(--t-label); }
.btn--ghost.btn--sm { padding: 0.5rem 1.0625rem; }
.btn--block { width: 100%; }

/* ───────────────────────────────────────────────────────────────
   CARD — 1px border + L-brackets on hover
   ─────────────────────────────────────────────────────────────── */
.card {
  position: relative; display: block;   /* so <a class="card"> works */
  border: var(--rule-w) solid var(--rule);
  background: var(--bg-raised);
  padding: var(--s-md);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.card::before, .card::after {
  content: ''; position: absolute;
  width: var(--bracket); height: var(--bracket);
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.card::before {
  top: -1px; left: -1px;
  border-top: var(--rule-w-heavy) solid var(--signal);
  border-left: var(--rule-w-heavy) solid var(--signal);
}
.card::after {
  bottom: -1px; right: -1px;
  border-bottom: var(--rule-w-heavy) solid var(--signal);
  border-right: var(--rule-w-heavy) solid var(--signal);
}
.card:hover { background: var(--bg-raised-hi); border-color: var(--rule-hi); }
.card:hover::before, .card:hover::after { opacity: 1; }

/* Always-on brackets — for featured / selected panels */
.card--marked::before, .card--marked::after { opacity: 1; }
.card--featured {
  border-color: var(--signal);
  background: var(--bg-signal-wash);
}
.card--flat { background: transparent; }

/* Standalone bracket utility — wrap an image or any block */
.marked { position: relative; }
.marked::before, .marked::after {
  content: ''; position: absolute;
  width: 1.25rem; height: 1.25rem; pointer-events: none;
}
.marked::before {
  top: -1px; left: -1px;
  border-top: var(--rule-w-heavy) solid var(--signal);
  border-left: var(--rule-w-heavy) solid var(--signal);
}
.marked::after {
  bottom: -1px; right: -1px;
  border-bottom: var(--rule-w-heavy) solid var(--signal);
  border-right: var(--rule-w-heavy) solid var(--signal);
}

/* ───────────────────────────────────────────────────────────────
   PANEL — the "window chrome" container (spec sheets, previews)
   ─────────────────────────────────────────────────────────────── */
.panel {
  position: relative;
  border: var(--rule-w) solid var(--rule);
  background: var(--bg-sunken);
}
.panel__head {
  display: flex; align-items: center; gap: var(--s-sm);
  padding: var(--s-sm) var(--s-md);
  border-bottom: var(--rule-w) solid var(--rule);
  font-size: var(--t-micro); letter-spacing: var(--ls-micro);
  color: var(--fg-muted);
}
.panel__body { padding: var(--s-md); }
.panel__foot {
  display: flex; align-items: center; gap: var(--s-sm);
  padding: var(--s-sm) var(--s-md);
  border-top: var(--rule-w) solid var(--rule);
  font-size: var(--t-micro); letter-spacing: var(--ls-micro);
  color: var(--fg-muted);
}

/* Spec row — key/value pairs. The "Fig. 01" pattern. */
.spec { display: flex; flex-direction: column; }
.spec__row {
  display: flex; align-items: baseline; gap: var(--s-md);
  padding: var(--s-sm) 0;
  border-bottom: var(--rule-w) solid var(--rule);
}
.spec__row:last-child { border-bottom: 0; }
.spec__key {
  flex: 0 0 34%;
  font-size: var(--t-label); letter-spacing: var(--ls-label);
  color: var(--fg-dim);
}
/* min-width:0 + overflow-wrap so long urls and emails can't blow out the
   row — mono has no natural break opportunities in a url. */
.spec__val {
  flex: 1; min-width: 0;
  font-size: var(--t-body-sm); color: var(--fg);
  overflow-wrap: anywhere;
}
@media (max-width: 767px) {
  .spec__row { flex-direction: column; gap: var(--s-xs); }
  .spec__key { flex: none; }
}

/* ───────────────────────────────────────────────────────────────
   RECORD ROW — timeline / experience entries
   ─────────────────────────────────────────────────────────────── */
.record {
  position: relative;
  display: grid; grid-template-columns: 1fr; gap: var(--s-sm);
  padding: var(--s-md) 0;
  border-top: var(--rule-w) solid var(--rule);
  transition: background var(--dur) var(--ease);
}
.record:last-child { border-bottom: var(--rule-w) solid var(--rule); }
.record::after {
  content: ''; position: absolute; left: 0; right: 0; top: -1px;
  height: var(--rule-w); background: var(--signal);
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
.record:hover::after { opacity: 1; }
.record__meta {
  font-size: var(--t-label); letter-spacing: var(--ls-label);
  color: var(--fg-dim); font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;   /* meta may hold a url, not just a date */
}
@media (min-width: 768px) {
  .record { grid-template-columns: 10rem 1fr; gap: var(--s-lg); padding: var(--s-md) 0; }
}

/* ───────────────────────────────────────────────────────────────
   STATS + STEPS
   ─────────────────────────────────────────────────────────────── */
.stat__num {
  font-size: 2.5rem; font-weight: var(--w-bold); line-height: 1;
  letter-spacing: var(--ls-display); color: var(--fg-signal);
  font-variant-numeric: tabular-nums;
}
.stat__label {
  margin-top: var(--s-sm);
  font-size: var(--t-label); letter-spacing: var(--ls-label);
  color: var(--fg-muted);
}
.step__num {
  font-size: 3.5rem; font-weight: var(--w-bold); line-height: 1;
  letter-spacing: var(--ls-display);
  color: rgba(255,255,255,0.08); user-select: none;
  transition: color var(--dur) var(--ease);
  font-variant-numeric: tabular-nums;
}
.step:hover .step__num { color: rgba(255,255,255,0.16); }

/* Segmented progress / capability meter */
.segments { display: flex; gap: 3px; }
.segments > i { display: block; height: 3px; flex: 1; background: var(--rule-hi); }
.segments > i.on { background: var(--signal); }

/* ───────────────────────────────────────────────────────────────
   LOGO — inline SVG, no background plate. Inherits currentColor so
   it sits directly on whatever surface it's placed on.
   ─────────────────────────────────────────────────────────────── */
.logo { display: flex; align-items: center; gap: var(--s-sm); color: var(--fg); }
.logo svg { width: 1.375rem; height: auto; fill: currentColor; flex-shrink: 0; }
.logo:hover { color: var(--fg-signal); }

/* ───────────────────────────────────────────────────────────────
   NAV + HEADER
   ─────────────────────────────────────────────────────────────── */
.header {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  height: var(--header-h); display: flex; align-items: center;
  justify-content: space-between;
  padding-inline: var(--margin-sm);
  background: var(--bg);
  border-bottom: var(--rule-w) solid var(--rule);
  transition: background var(--dur) var(--ease);
}
.header.is-scrolled { background: var(--bg-sunken); }
@media (min-width: 768px) { .header { padding-inline: var(--margin); } }

/* Selected state matches .tab exactly — same 2px signal underline — because
   a nav link marking the section you're in is doing the same job as a
   selected tab. `.is-active` is set by the scrollspy in the page script. */
.navlink {
  font-size: var(--t-label); font-weight: var(--w-med);
  letter-spacing: var(--ls-label); color: var(--fg-muted);
  padding-block: var(--s-xs); padding-inline: var(--s-xs);
  border-bottom: var(--rule-w-heavy) solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.navlink:hover, .navlink.is-active { color: var(--fg-signal); border-bottom-color: var(--signal); }

/* ───────────────────────────────────────────────────────────────
   TABS
   ─────────────────────────────────────────────────────────────── */
.tabs {
  display: flex; overflow-x: auto;
  border-bottom: var(--rule-w) solid var(--rule);
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  font-family: var(--font);
  font-size: var(--t-label); font-weight: var(--w-med);
  letter-spacing: var(--ls-label);
  color: var(--fg-dim); background: none; border: 0;
  padding: var(--s-sm) 1rem; cursor: pointer; white-space: nowrap;
  border-bottom: var(--rule-w-heavy) solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tab:hover, .tab.is-active { color: var(--fg-signal); border-bottom-color: var(--signal); }
.tabpanel[hidden] { display: none; }

/* ───────────────────────────────────────────────────────────────
   ACCORDION
   ─────────────────────────────────────────────────────────────── */
.acc { border: var(--rule-w) solid var(--rule); transition: background var(--dur) var(--ease); }
.acc:hover { background: var(--bg-raised); }
.acc__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-md); padding: var(--s-md); cursor: pointer;
  font-size: var(--t-body); font-weight: var(--w-med); color: var(--fg);
  list-style: none;
}
.acc__head::-webkit-details-marker { display: none; }
.acc__sign {
  position: relative; width: 0.75rem; height: 0.75rem; flex-shrink: 0;
  transition: transform var(--dur) var(--ease);
}
.acc__sign::before, .acc__sign::after {
  content: ''; position: absolute; background: var(--fg-muted);
  transition: background var(--dur) var(--ease);
}
.acc__sign::before { left: 0; top: 50%; width: 100%; height: 1px; transform: translateY(-50%); }
.acc__sign::after  { top: 0; left: 50%; height: 100%; width: 1px; transform: translateX(-50%); }
.acc[open] .acc__sign { transform: rotate(45deg); }
.acc[open] .acc__sign::before, .acc[open] .acc__sign::after { background: var(--signal); }
.acc__body { padding: 0 var(--s-md) var(--s-md); }

/* ───────────────────────────────────────────────────────────────
   FORM — underline default, full box on focus
   ─────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field__label {
  font-size: var(--t-micro); letter-spacing: var(--ls-micro);
  color: var(--fg-muted);
}
.input, .textarea, .select {
  width: 100%;
  font-family: var(--font); font-size: var(--t-body-sm);
  color: var(--fg); background: var(--bg-sunken);
  border: var(--rule-w) solid transparent;
  border-bottom: var(--rule-w-heavy) solid var(--rule-hi);
  padding: var(--s-sm); outline: none;
  transition: border-color var(--dur-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-dim); }
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--signal);
}
.textarea { resize: vertical; min-height: 6rem; }
.select { appearance: none; cursor: pointer; }

/* ───────────────────────────────────────────────────────────────
   CODE + TABLE — for docs / case-study page types
   ─────────────────────────────────────────────────────────────── */
.code {
  font-family: var(--font); font-size: var(--t-body-sm);
  color: var(--fg-body); background: var(--bg-sunken);
  border: var(--rule-w) solid var(--rule);
  border-left: var(--rule-w-heavy) solid var(--signal);
  padding: var(--s-md); margin: 0;
  overflow-x: auto; line-height: 1.6; white-space: pre;
  -moz-tab-size: 2; tab-size: 2;
}

.table { width: 100%; border-collapse: collapse; font-size: var(--t-body-sm); }
.table th, .table td {
  text-align: left; padding: 0.625rem 0.75rem; vertical-align: top;
  border-bottom: var(--rule-w) solid var(--rule);
}
.table th {
  font-size: var(--t-label); font-weight: var(--w-med);
  letter-spacing: var(--ls-label); color: var(--fg-muted);
  border-bottom-color: var(--rule-hi);
}
.table td { color: var(--fg-body); }
.table td:first-child { color: var(--fg); white-space: nowrap; }
.table tbody tr:hover td { background: var(--bg-raised); }
.table-scroll { overflow-x: auto; }

/* ───────────────────────────────────────────────────────────────
   MEDIA — portrait / project imagery
   ─────────────────────────────────────────────────────────────── */
.media {
  position: relative; overflow: hidden;
  border: var(--rule-w) solid var(--rule);
  background: var(--bg-sunken);
}
.media img {
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(1) contrast(1.05);
  transition: filter var(--dur) var(--ease), transform 0.4s var(--ease);
}
.media:hover img { filter: grayscale(0.4) contrast(1); transform: scale(1.02); }

/* Face crop. On a box shorter than the source, `cover` would trim evenly
   from top and bottom and cut the forehead; biasing the frame upward keeps
   the head whole and lands the face just above the optical centre. Pair
   with a squarer aspect-ratio when a portrait column runs too tall. */
.media--face img { object-position: center 36%; }

/* ───────────────────────────────────────────────────────────────
   LIST — a 16px yellow dash instead of a disc.
   Defined here, above the utility block, so .mt-* can override its
   margin. A component whose own margin is declared after the
   utilities would silently win at equal specificity.
   ─────────────────────────────────────────────────────────────── */
.list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: var(--s-sm);
}
.list > li {
  display: flex; align-items: flex-start; gap: var(--s-sm);
  font-size: var(--t-body-sm); color: var(--fg-body);
}
.list > li::before {
  content: ''; flex-shrink: 0; width: 1rem; height: var(--rule-w);
  background: var(--signal); margin-top: 0.7em;
}
/* a list following body copy always gets air, without needing .mt-md */
p + .list { margin-top: var(--s-md); }

/* ───────────────────────────────────────────────────────────────
   UTILITIES
   ─────────────────────────────────────────────────────────────── */
.stack   { display: flex; flex-direction: column; }
.row     { display: flex; align-items: center; }
.wrap-r  { flex-wrap: wrap; }
.between { justify-content: space-between; }
.gap-xs  { gap: var(--s-xs); }
.gap-sm  { gap: var(--s-sm); }
.gap-md  { gap: var(--s-md); }
.gap-lg  { gap: var(--s-lg); }
.mt-sm { margin-top: var(--s-sm); }  .mt-md { margin-top: var(--s-md); }
.mt-lg { margin-top: var(--s-lg); }  .mb-sm { margin-bottom: var(--s-sm); }
.mb-md { margin-bottom: var(--s-md); } .mb-lg { margin-bottom: var(--s-lg); }
.maxw-prose { max-width: 60ch; }
.only-md { display: none; }
@media (min-width: 768px) { .only-md { display: flex; } }
.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;
}
