/* ===========================================================================
   V3 · delta over precision-v2.css
   ---------------------------------------------------------------------------
   1  Thesis: the paragraph leads
   2  The turn: one line, Dia Text Reveal, no hairlines
   3  The console: a full interface frame
   4  Functions: three across
   5  AI layer: scenes that depict their claim

   Motion rule for the whole file: every animation sits ON TOP of a finished
   base state and is applied only under `html.js` once the block has been
   seen. Scripts blocked, motion reduced, or the observer never firing all
   leave the finished thing on screen. Nothing here is load-bearing.
   ======================================================================== */

/* ---------------------------------------------------------------------------
   1 · THESIS — the paragraph is the lead
   ----------------------------------------------------------------------------
   The headline is gone at the client's direction and the paragraph opens the
   band. It keeps the scroll highlight, and it is set larger than a lede
   because it is now doing a headline's job.

   The section still has an <h2>, visually hidden. `aria-labelledby` points at
   it and the nav links to it, so the band keeps its name in the accessibility
   tree and in a heading list. Promoting a 44-word paragraph to <h2> would
   have kept the structure and wrecked heading navigation.
   ------------------------------------------------------------------------ */
/* Full container width and set bold, at the client's direction. `max-width`
   is released rather than raised: the point is that it follows the content
   column, so it should take whatever that column is at any viewport.

   Weight is 600, which is this system's ceiling. The tracking tightens with
   it: bold text at default tracking opens up and reads loose, and at this
   size across a full column that is very visible. */
/* The cap lives on the wrapper, not the paragraph. Releasing only the
   paragraph looks like it should work and changes nothing, because the
   wrapper is still 62ch wide and the paragraph can only fill its parent. */
.p-thesis__lead--v3 { max-width: none; }

.p-thesis__lead--v3 .p-thesis__lede {
  max-width: none;
  font-size: clamp(1.375rem, 1.05rem + 1.35vw, 2rem);
  font-weight: var(--weight-semibold);
  line-height: 1.35;
  letter-spacing: -0.022em;
}

/* The scroll highlight sets colour per word, so the weight has to reach the
   spans rather than stopping at the paragraph. */
.p-thesis__lead--v3 .p-scrollhl__w { font-weight: inherit; }

/* ---------------------------------------------------------------------------
   2 · THE TURN — two lines, no hairlines
   ----------------------------------------------------------------------------
   The band's own top rule goes, and so does the one belonging to the section
   after it. A statement given this much space should sit in open page; a rule
   above and below turns the pause into a box.
   ------------------------------------------------------------------------ */
.p-turn,
.p-turn + .p-section {
  border-top: 0;
}

.p-turn__line + .p-turn__line {
  margin-top: var(--s-4);
}

/* ---------------------------------------------------------------------------
   3 · THE CONSOLE
   ----------------------------------------------------------------------------
   A full application frame. Its palette is the panel subsystem's, not the
   page's, so it stays a screenshot of a product rather than a section of this
   website wearing a border.
   ------------------------------------------------------------------------ */
.c-console { margin: 0; }

.c-console__frame {
  display: grid;
  grid-template-columns: 1fr;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--panel);
  outline: 1px solid var(--hairline-strong);
  color: var(--panel-ink);
}

@media (min-width: 56em) {
  .c-console__frame { grid-template-columns: 196px 1fr; }
}

/* --- The frame's spacing scale ------------------------------------------
   One set of values for the whole shell, so padding and gaps cannot drift
   apart card by card. Everything below refers to these rather than reaching
   for a spacing token directly.

   They step up at 56em, where the rail appears and the frame stops being a
   narrow column: the same padding that reads generous at 375px reads mean at
   1440px. */
.c-console__frame {
  --c-pad: var(--s-4);
  --c-gap: var(--s-4);
  --c-card-pad: var(--s-4);
  --c-row-gap: var(--s-4);
}

@media (min-width: 56em) {
  .c-console__frame {
    --c-pad: var(--s-6);
    --c-gap: var(--s-6);
    --c-card-pad: var(--s-6);
    --c-row-gap: var(--s-4);
  }
}

/* A grid item defaults to `min-width: auto`, so it refuses to shrink below its
   content's minimum. At 375px that pushed the main column 43px past the frame
   and the top bar was clipped. Every level from the frame down to the row
   contents has to opt out for the shell to actually fit. */
.c-main,
.c-body,
.c-stats,
.c-grid,
.c-card,
.c-ship { min-width: 0; }

.c-icon { width: 16px; height: 16px; flex: none; }

/* --- Rail ---------------------------------------------------------------- */
.c-rail {
  display: none;
  flex-direction: column;
  gap: var(--s-6);
  padding: var(--c-pad) var(--s-4);
  background: var(--panel-sunken);
  border-right: 1px solid var(--panel-line);
}

@media (min-width: 56em) { .c-rail { display: flex; } }

.c-rail__brand {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-2) var(--s-3);
}

.c-rail__mark {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: var(--panel-accent);
  flex: none;
}

.c-rail__name {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--panel-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.c-rail__nav { display: flex; flex-direction: column; gap: 2px; }

.c-rail__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  color: var(--panel-ink-faint);
  transition: color var(--fast) var(--ease-out), background-color var(--fast) var(--ease-out);
}

/* The current item is the only lit thing in the rail. Marked by ground and
   ink together, never by colour alone. */
.c-rail__item.is-current {
  background: color-mix(in srgb, var(--panel-accent) 16%, transparent);
  color: var(--panel-ink);
}

.c-rail__item.is-current .c-icon { color: var(--panel-accent); }

/* --- Top bar ------------------------------------------------------------- */
.c-topbar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--c-pad);
  border-bottom: 1px solid var(--panel-line);
  background: var(--panel);
}

.c-search {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--radius-sm);
  background: var(--panel-sunken);
  border: 1px solid var(--panel-line);
  color: var(--panel-ink-faint);
}

.c-search__icon { color: var(--panel-ink-faint); }

.c-search__text {
  font-size: var(--text-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.c-topbar__right { display: flex; align-items: center; gap: var(--s-3); flex: none; }

.c-bell { position: relative; display: flex; color: var(--panel-ink-faint); }

.c-bell__dot {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--panel-flag);
  outline: 2px solid var(--panel);
}

.c-avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--panel-accent) 22%, var(--panel-raised));
  color: var(--panel-ink);
  font-size: 11px;
  font-weight: var(--weight-medium);
  letter-spacing: 0.02em;
}

/* --- Body ---------------------------------------------------------------- */
.c-body { padding: var(--c-pad); display: flex; flex-direction: column; gap: var(--c-gap); }

.c-body__head { display: flex; align-items: baseline; gap: var(--s-3); }

.c-body__title {
  font-size: var(--text-h4);
  font-weight: var(--weight-medium);
  color: var(--panel-ink);
  margin: 0;
}

.c-body__sub {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--panel-ink-faint);
}

/* --- Summary tiles ------------------------------------------------------- */
.c-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--c-gap);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 40em) { .c-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.c-stat {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4);
  border-radius: var(--radius-md);
  background: var(--panel-raised);
  border: 1px solid var(--panel-line);
}

/* One tile in accent, one in each state, one plain. Tinting every tile is
   the same as tinting none. */
.c-stat[data-tone='accent'] {
  background: color-mix(in srgb, var(--panel-accent) 14%, var(--panel-raised));
  border-color: color-mix(in srgb, var(--panel-accent) 34%, transparent);
}

.c-stat[data-tone='accent'] .c-stat__value { color: var(--panel-accent); }
.c-stat[data-tone='ok'] .c-stat__delta { color: var(--panel-ok); }
.c-stat[data-tone='flag'] .c-stat__delta { color: var(--panel-flag); }

.c-stat__label {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--panel-ink-faint);
}

.c-stat__row { display: flex; align-items: baseline; gap: var(--s-2); }

.c-stat__value {
  font-size: 1.375rem;
  font-weight: var(--weight-medium);
  line-height: 1;
  color: var(--panel-ink);
  font-variant-numeric: tabular-nums;
}

.c-stat__delta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--panel-ink-faint);
}

/* --- Card grid ----------------------------------------------------------- */
.c-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--c-gap);
}

@media (min-width: 52em) {
  .c-grid { grid-template-columns: 1.35fr 1fr; }
  .c-card--ships { grid-column: 1 / -1; }
}

.c-card {
  padding: var(--c-card-pad);
  border-radius: var(--radius-md);
  background: var(--panel-raised);
  border: 1px solid var(--panel-line);
  min-width: 0;
}

.c-card__title {
  margin: 0 0 var(--s-4);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--panel-ink);
}

/* --- Chart --------------------------------------------------------------- */
.c-chart { color: var(--panel-accent); }

.c-chart__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}

.c-chart__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--panel-ink);
}

.c-chart__caption {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--panel-ink-faint);
}

.c-chart__svg { display: block; width: 100%; height: 84px; overflow: visible; }

/* --- Shipment rows ------------------------------------------------------- */
.c-ships { list-style: none; margin: 0; padding: 0; }

.c-ship {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: 'ref state' 'lane eta' 'track track';
  gap: 2px var(--s-3);
  padding: var(--c-row-gap) 0;
  border-top: 1px solid var(--panel-line);
}

.c-ship:first-child { border-top: 0; padding-top: 0; }

@media (min-width: 44em) {
  .c-ship {
    grid-template-columns: 152px 1fr 96px 84px;
    grid-template-areas: 'ref lane state eta' 'track track track track';
    align-items: center;
  }
}

.c-ship__ref {
  grid-area: ref;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--panel-ink);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-ship__lane {
  grid-area: lane;
  font-size: var(--text-xs);
  color: var(--panel-ink-muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.c-ship__eta {
  grid-area: eta;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--panel-ink-faint);
  text-align: right;
}

.c-ship__state {
  grid-area: state;
  justify-self: start;
  padding: 2px var(--s-2);
  border-radius: 999px;
  border: 1px solid currentColor;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--panel-ink-faint);
}

.c-ship[data-state='transit'] .c-ship__state { color: var(--panel-accent); }
.c-ship[data-state='customs'] .c-ship__state { color: var(--panel-accent-alt); }
.c-ship[data-state='flagged'] .c-ship__state { color: var(--panel-flag); }
.c-ship[data-state='ok'] .c-ship__state { color: var(--panel-ok); }

.c-ship__track {
  grid-area: track;
  margin-top: var(--s-2);
  height: 3px;
  border-radius: 999px;
  background: var(--panel-sunken);
  overflow: hidden;
}

.c-ship__fill {
  display: block;
  height: 100%;
  width: var(--p);
  border-radius: inherit;
  background: var(--panel-accent);
}

.c-ship[data-state='customs'] .c-ship__fill { background: var(--panel-accent-alt); }
.c-ship[data-state='flagged'] .c-ship__fill { background: var(--panel-flag); }
.c-ship[data-state='ok'] .c-ship__fill { background: var(--panel-ok); }

/* --- Attention queue ----------------------------------------------------- */
.c-todo { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--c-row-gap); }

.c-todo__item {
  display: grid;
  grid-template-columns: 8px 1fr;
  gap: var(--s-1) var(--s-3);
  align-items: start;
}

.c-todo__mark {
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border-radius: 2px;
  background: var(--panel-ink-faint);
}

.c-todo__item[data-tone='flag'] .c-todo__mark { background: var(--panel-flag); }
.c-todo__item[data-tone='ok'] .c-todo__mark { background: var(--panel-ok); }

.c-todo__text { font-size: var(--text-xs); color: var(--panel-ink-muted); line-height: 1.45; }

.c-todo__ref {
  grid-column: 2;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--panel-ink-faint);
}

/* --- The label, on the frame -------------------------------------------- */
.c-console__note {
  margin-top: var(--s-3);
  font-size: var(--text-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-tertiary);
}

/* --- Console motion -----------------------------------------------------
   Applied only under `html.js` and only once `.is-in` lands, so the finished
   frame is what renders when any of it fails. */
.js .c-console .c-stat,
.js .c-console .c-ship,
.js .c-console .c-todo__item {
  opacity: 0;
  transform: translate3d(0, 8px, 0);
}

.js .c-console.is-in .c-stat,
.js .c-console.is-in .c-ship,
.js .c-console.is-in .c-todo__item {
  opacity: 1;
  transform: none;
  transition: opacity var(--base) var(--ease-out) calc(var(--i, 0) * 70ms),
    transform var(--base) var(--ease-out) calc(var(--i, 0) * 70ms);
}

.js .c-console .c-ship__fill { transform: scaleX(0); transform-origin: left; }

.js .c-console.is-in .c-ship__fill {
  transform: scaleX(1);
  transition: transform 900ms var(--ease-out) calc(240ms + var(--i, 0) * 70ms);
}

/* The chart draws itself. `pathLength` is not set, so the dash values are in
   user units and generous enough to cover the longest path this data makes. */
.js .c-console .c-chart__line { stroke-dasharray: 600; stroke-dashoffset: 600; }
.js .c-console .c-chart__area { opacity: 0; }
.js .c-console .c-chart__dot { opacity: 0; transform: scale(0.4); transform-origin: center; }

.js .c-console.is-in .c-chart__line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1400ms var(--ease-out) 200ms;
}

.js .c-console.is-in .c-chart__area {
  opacity: 1;
  transition: opacity 700ms var(--ease-out) 900ms;
}

.js .c-console.is-in .c-chart__dot {
  opacity: 1;
  transform: scale(1);
  transition: opacity 300ms var(--ease-out) 1500ms, transform 400ms var(--ease-out) 1500ms;
}

/* The search field shimmers once as the frame settles, the way a focused
   input catches light. One pass, not a loop. */
.js .c-console.is-in .c-search::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    100deg,
    transparent 40%,
    color-mix(in srgb, var(--panel-ink) 12%, transparent) 50%,
    transparent 60%
  );
  background-size: 300% 100%;
  animation: p-shimmer-once 1800ms var(--ease-out) 1200ms 1;
  pointer-events: none;
}

.c-search { position: relative; overflow: hidden; }

@keyframes p-shimmer-once {
  from { background-position: 130% 0; }
  to { background-position: -30% 0; }
}

/* The live notification dot breathes. Slow, and it is the only looping thing
   in the frame. */
.js .c-console.is-in .c-bell__dot { animation: c-breathe 3.2s var(--ease-out) infinite; }

@keyframes c-breathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(0.86); }
}

@media (prefers-reduced-motion: reduce) {
  .js .c-console .c-stat,
  .js .c-console .c-ship,
  .js .c-console .c-todo__item { opacity: 1; transform: none; transition: none; }
  .js .c-console .c-ship__fill { transform: scaleX(1); transition: none; }
  .js .c-console .c-chart__line { stroke-dashoffset: 0; transition: none; }
  .js .c-console .c-chart__area,
  .js .c-console .c-chart__dot { opacity: 1; transform: none; transition: none; }
  .js .c-console.is-in .c-search::after { animation: none; content: none; }
  .js .c-console.is-in .c-bell__dot { animation: none; }
}

/* ---------------------------------------------------------------------------
   4 · FUNCTIONS — three across
   ----------------------------------------------------------------------------
   Six items in a three-column grid. A true 3x3 would need nine, and the extra
   three would have to be invented; the grid reads as a grid at six.

   The lead-plus-three shape from variant A is dropped here: it existed to
   break a four-across row that rhymed with the AI cards below, and at three
   columns against four cards there is no rhyme left to break.
   ------------------------------------------------------------------------ */
@media (min-width: 40em) {
  .p-functions--grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 62em) {
  .p-functions--grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.p-functions--grid .p-functions__item {
  padding-inline: var(--s-6);
  padding-block: var(--s-8);
}

/* --- The icon above each title -------------------------------------------
   Boxed rather than bare, so six small strokes read as a row of six things
   at a glance instead of six smudges. The accent tint is the same treatment
   the console's current rail item gets, which keeps one idea of "this is the
   lit state" across the page.

   `aria-hidden` in the markup: the title beneath says the same thing, and an
   icon that repeats its own label is noise in a screen reader. */
.p-functions__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: var(--s-4);
  border-radius: var(--radius-md);
  background: var(--accent-tint);
  color: var(--accent);
}

.p-functions__icon svg { width: 20px; height: 20px; }

@media (min-width: 62em) {
  /* First of each row flush left, last flush right, so the grid's outer
     edges line up with the container rather than sitting inside a gutter. */
  .p-functions--grid .p-functions__item:nth-child(3n + 1) { padding-inline: 0 var(--s-6); }
  .p-functions--grid .p-functions__item:nth-child(3n) { padding-inline: var(--s-6) 0; }
}

/* ---------------------------------------------------------------------------
   5 · AI LAYER — scenes that depict their claim
   ----------------------------------------------------------------------------
   Colour is rationed to one element per scene: the thing the card is about.
   Everything else is currentColor at reduced opacity.
   ------------------------------------------------------------------------ */
.a-mock { display: block; width: 100%; height: auto; color: var(--ink-tertiary); }

.p-ai__stage {
  background: var(--surface-sunken);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--s-4);
  overflow: hidden;
}

.a-panel { stroke: currentColor; opacity: 0.5; }
.a-line { fill: currentColor; stroke: none; opacity: 0.75; }
.a-line--dim { opacity: 0.35; }
.a-bar { fill: currentColor; stroke: none; opacity: 0.4; }
.a-track { stroke: currentColor; opacity: 0.3; stroke-width: 2; }
.a-node { fill: var(--surface-sunken); stroke: currentColor; opacity: 0.55; }
.a-btn { fill: none; stroke: currentColor; opacity: 0.4; }

/* The one lit element per scene. */
.a-catch__box { fill: none; stroke: var(--panel-flag); opacity: 1; }
.a-catch__dot { fill: var(--panel-flag); stroke: none; }
.a-catch__mark { stroke: var(--canvas); stroke-width: 1.6; }
.a-node--done { stroke: var(--panel-ok); opacity: 1; }
.a-tick { stroke: var(--panel-ok); stroke-width: 1.6; }
.a-node--live { stroke: var(--accent); fill: var(--accent); opacity: 1; }
.a-pulse { stroke: var(--accent); fill: none; opacity: 0; }
.a-track--fill { stroke: var(--accent); opacity: 1; stroke-dasharray: 76; stroke-dashoffset: 38; }
.a-bar--new { fill: var(--accent); opacity: 1; }
.a-btn--go { fill: var(--accent); stroke: none; opacity: 1; }
.a-cursor { fill: var(--accent-contrast); stroke: none; opacity: 0.85; }

/* --- AI motion ----------------------------------------------------------
   One loop per scene, slow, and only after the band has been seen. These sit
   four across beside reading copy; four fast loops next to a paragraph is a
   page that cannot be read. */
.js .p-ai__grid.is-in .a-pulse {
  animation: a-pulse 3.4s var(--ease-out) infinite;
}

@keyframes a-pulse {
  0% { opacity: 0.5; transform: scale(1); transform-origin: 60px 48px; }
  70%, 100% { opacity: 0; transform: scale(2.1); transform-origin: 60px 48px; }
}

.js .p-ai__grid.is-in .a-track--fill {
  animation: a-fill 3.4s var(--ease-out) infinite;
}

@keyframes a-fill {
  0%, 10% { stroke-dashoffset: 76; }
  55%, 100% { stroke-dashoffset: 38; }
}

.js .p-ai__grid.is-in .a-bar--new {
  animation: a-land 4s var(--ease-out) infinite;
}

@keyframes a-land {
  0% { opacity: 0; transform: translateY(-6px); }
  18%, 82% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-6px); }
}

.js .p-ai__grid.is-in .a-catch__dot,
.js .p-ai__grid.is-in .a-catch__mark {
  animation: a-flag 3.8s var(--ease-out) infinite;
}

@keyframes a-flag {
  0%, 55% { opacity: 0; }
  62%, 100% { opacity: 1; }
}

.js .p-ai__grid.is-in .a-cursor {
  animation: a-press 3.6s var(--ease-out) infinite;
}

@keyframes a-press {
  0%, 40% { transform: translate(6px, 5px); opacity: 0; }
  52% { transform: none; opacity: 0.85; }
  60% { transform: translateY(1px); opacity: 0.85; }
  70%, 100% { transform: none; opacity: 0.85; }
}

@media (prefers-reduced-motion: reduce) {
  .js .p-ai__grid.is-in .a-pulse,
  .js .p-ai__grid.is-in .a-track--fill,
  .js .p-ai__grid.is-in .a-bar--new,
  .js .p-ai__grid.is-in .a-catch__dot,
  .js .p-ai__grid.is-in .a-catch__mark,
  .js .p-ai__grid.is-in .a-cursor { animation: none; }
}
