/* ============================================================================
   Project 118 — layout and components
   ========================================================================= */
*,*::before,*::after{box-sizing:border-box}
/* [hidden] is a hint, not a rule — any element with its own display value wins.
   Half the toggles on this site set the attribute and expect it to work, so make
   it mean what everybody assumes it means. */
[hidden]{display:none!important}
html,body{margin:0;height:100%}
body{
  background:var(--studio); color:var(--ink); font:var(--t-body);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  overflow:hidden;
}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
a{color:inherit;text-decoration:none}
:focus-visible{outline:1.5px solid var(--green);outline-offset:3px}

.label{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--secondary)}
.mono{font:var(--t-mono);letter-spacing:.02em}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}

/* ---------------------------------------------------------------- identity */
/* Centred PROJECT / 118 lockup, per the design reference. The number is the mark,
   so it gets the room; everything else defers to it. */
#identity{
  position:fixed;top:22px;left:0;right:0;z-index:40;pointer-events:none;
  display:flex;flex-direction:column;align-items:center;gap:2px;text-align:center;
}
#identity .lockup{
  pointer-events:auto;text-decoration:none;display:flex;flex-direction:column;
  align-items:center;gap:1px;
}
#identity .kicker{
  font:500 10px/1 var(--display);letter-spacing:.34em;text-transform:uppercase;
  color:var(--secondary);padding-left:.34em;   /* optical centring against the tracking */
}
#identity .mark{
  font:600 clamp(46px,5.4vw,72px)/0.9 var(--display);
  letter-spacing:-0.01em;color:var(--green);display:block;
}
/* The identity line sits top-left rather than under the lockup: stacked, it
   crowded the mark and the three lines fought each other. */
#identity .who{position:absolute;left:var(--gut);top:6px;text-align:left;display:block}
#identity .who .n{font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--secondary);display:block}
#identity .who .d{font:var(--t-small);color:var(--ink-soft);display:block;margin-top:3px}

/* THE HATCH THAT CLOSED THE HEADER BAND IS GONE, 25 AUGUST.
   It was a technical-drawing motif ruled across the full width at 210px, and
   the backdrop puts its own horizon at very nearly the same height. Two
   horizontals a few pixels apart do not read as a header rule and a horizon —
   they read as one horizon drawn twice, badly, and the eye keeps going back to
   ask which one the car is standing on. The backdrop's is the real one: it
   moves with the camera because it is IN the scene, while this was pinned to
   the window and slid across the car whenever the view tilted.

   The motif survives where it does not compete: on the loading overlay
   (`#boot::after`), where there is no backdrop and nothing to argue with.
   If the header band ever needs closing again, close it with space rather than
   a second line. */
/* THE MASTHEAD COSTS A THIRD OF A PHONE. Lockup, identity line, context line
   and hatch came to roughly 320px before the car began, on a screen whose whole
   proposition is the car — and the car was then fitted into what was left,
   which is why it floated in the upper half with a dead band beneath it.

   Same lockup, same elements, half the height. The mark stays the mark. */
@media(max-width:760px){
  #identity{top:12px}
  #identity .kicker{font-size:8.5px;letter-spacing:.3em;padding-left:.3em}
  #identity .mark{font-size:31px}
  /* nothing to the left of the lockup on a phone — put the line back beneath it */
  #identity .who{position:static;text-align:center;margin-top:5px}
  #identity .who .n{font-size:8.5px}
}

/* -------------------------------------------------------------- context bar
   Under the lockup, in the header band, centred: state · view · subject. It is
   deliberately quiet — it is a caption for the whole screen, not a control,
   and nothing in it is clickable except the subject, which clears itself. */
#ctx{
  position:fixed;top:118px;left:0;right:0;z-index:39;pointer-events:none;
  display:flex;justify-content:center;align-items:center;gap:0;
  font:var(--t-mono);letter-spacing:.05em;color:var(--secondary);
}
#ctx > span{padding:0 9px;position:relative;white-space:nowrap}
#ctx > span + span::before{
  content:'';position:absolute;left:-1px;top:50%;width:2px;height:2px;
  border-radius:50%;background:var(--rule);transform:translateY(-50%);
}
#ctx .subj{color:var(--ink);pointer-events:auto}
#ctx .subj em{font-style:normal;color:var(--secondary)}
#ctx .subj button{
  pointer-events:auto;color:var(--secondary);margin-left:7px;font:inherit;line-height:1;
}
#ctx .subj button:hover{color:var(--ink)}
@media(max-width:760px){
  /* the lockup stacks and the identity line moves under it, so the bar drops
     with them; below 420px there is no room for three segments and the subject
     carries the line on its own */
  #ctx{top:100px;font-size:11px;transition:opacity var(--t-ui) var(--ease)}
  #ctx > span{padding:0 7px}
}
@media(max-width:420px){
  #ctx[data-subject="true"] > span:not(.subj){display:none}
}

/* ------------------------------------------------------------- landing line
   THE ONE LOUD MOMENT, AND IT IS A COMPOSITION RATHER THAN A CAPTION.

   A column of type on the left, the car trucked over to the right to make room
   for it — the viewer does that itself, so the two are one arrangement rather
   than words laid over a picture. It holds for as long as it takes to read and
   then leaves: the first drag dismisses it and the car eases back to centre in
   the same movement.

   EVERY LINE BREAK IN HERE IS SET BY HAND. At this size nothing may wrap on
   its own — a hero that breaks where the column happens to end reads as an
   accident, because it is one. The words and their breaks live in
   vehicle.json; the type is sized so the longest of them fits. */
/* THE WORDS AND THE CAR ARE ONE GROUP, not two things at opposite edges.
   Pinned to the gutter, the statement sat hard against the left edge of a wide
   screen while the car stood over on the right, and the pair read as two
   separate compositions with a hole between them. It comes in off the edge —
   about a tenth of the window, and never past the point where the lines would
   start to crowd the car. */
#landing{
  position:fixed;left:max(var(--gut), 9vw);top:250px;z-index:38;
  max-width:calc(100% - 2*var(--gut));pointer-events:none;text-align:left;
  animation:landing-in 720ms var(--ease) both;
}
@keyframes landing-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){ #landing{animation:none} }
#landing[data-going="true"]{
  opacity:0;transform:translateY(-6px);
  transition:opacity 320ms var(--ease),transform 320ms var(--ease);
}

#landing .one,#landing .two{margin:0;white-space:nowrap}
#landing .one{
  font:600 clamp(27px,3.5vw,46px)/1.04 var(--display);
  letter-spacing:-0.032em;color:var(--ink);
}
#landing .two{
  margin-top:12px;
  font:500 clamp(17px,2.1vw,27px)/1.25 var(--display);
  letter-spacing:-0.018em;color:var(--green);
}
#landing .rule{display:block;width:52px;height:2px;background:var(--green);margin:22px 0 16px}
#landing .sub{margin:0;max-width:34ch;font:var(--t-small);color:var(--ink-soft);line-height:1.65}
#landing .act{
  pointer-events:auto;margin-top:22px;display:inline-flex;align-items:center;gap:9px;
  min-height:var(--tap);
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--green);border-bottom:1px solid var(--green);padding:0 0 5px;
}
#landing .act::after{content:'\2192';font-size:13px;line-height:1}
#landing .act:hover{color:var(--ink);border-bottom-color:var(--ink)}
#landing .x{
  pointer-events:auto;position:absolute;top:-14px;left:-12px;
  width:var(--tap);height:var(--tap);display:flex;align-items:center;
  justify-content:center;font-size:17px;color:var(--rule);
}
#landing .x:hover{color:var(--secondary)}

@media(max-width:820px){
  /* THE COLUMN IS THE SCREEN on a phone, so there is no column: the statement
     goes above the car and the car keeps the rest. Trucking it sideways here
     would push it off the glass, which is why the viewer's offset is dropped
     to nothing at this width and the composition stacks instead. */
  #landing{top:200px;right:var(--gut);max-width:none}
  #landing .one{font-size:clamp(25px,7vw,34px)}
  #landing .two{font-size:clamp(15px,4.2vw,20px);margin-top:9px}
  #landing .rule{margin:16px 0 12px}
  #landing .sub{max-width:38ch;font-size:13px}
  #landing .act{margin-top:16px}
  #landing .x{top:-16px;left:auto;right:-10px}
}

/* ------------------------------------------------------------------ topnav */
#topbar{position:fixed;top:30px;right:var(--gut);z-index:40;display:flex;gap:22px;align-items:center}
#topbar button{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);transition:color var(--t-ui) var(--ease)}
#topbar button[aria-current="true"],#topbar button:hover{color:var(--ink)}
#topbar .burger{display:inline-flex;align-items:center;justify-content:center;
  width:var(--tap);height:var(--tap);margin-right:-10px}
#topbar .burger svg{width:19px;height:14px;fill:none;stroke:currentColor;stroke-width:1.4}

/* ------------------------------------------------------------- phone tray */
/* Above 820px this does not exist: the controls have corners of their own and
   nothing is competing for the space. */
#tray{display:none}

/* THE MENU IS A PAGE. See the note in index.html for why it stopped being a
   drawer. Three groups, numbered, on the studio ground rather than on a white
   card — the card was the thing that read as a system panel bolted to the side
   of the site. */
#menu{
  position:fixed;inset:0;z-index:60;background:var(--studio);
  display:flex;flex-direction:column;
  padding:26px var(--gut) 22px;
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity var(--t-ui) var(--ease), transform var(--t-ui) var(--ease),
             visibility 0s linear var(--t-ui);
}
#menu[data-open="true"]{opacity:1;visibility:visible;transform:none;
  transition:opacity var(--t-ui) var(--ease), transform var(--t-ui) var(--ease),
             visibility 0s linear 0s}
#menu .mtop{display:flex;align-items:baseline;justify-content:space-between;gap:20px}
#menu .who{font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--secondary)}
#menu .close{font-size:22px;line-height:1;color:var(--secondary);flex:none}
#menu .close:hover{color:var(--ink)}
#menu .mcols{
  flex:1;display:grid;grid-template-columns:repeat(3,1fr);gap:0 34px;
  align-content:center;padding:20px 0;min-height:0;
}
#menu .grp{border-top:1px solid var(--rule);padding-top:12px}
#menu .grp .lab{display:block;margin-bottom:8px;font:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;color:var(--secondary)}
#menu .grp a{
  display:block;padding:7px 0;color:var(--ink);
  font:500 clamp(21px,2.3vw,30px)/1.15 var(--sans);letter-spacing:-0.02em;
  transition:color var(--t-ui) var(--ease);
}
#menu .grp a:hover{color:var(--green)}
/* The number is a countable index, not a label: it stays out of the way until
   you are looking for it. */
#menu .grp a .n{display:inline-block;width:2.1em;font:var(--t-mono);
  color:var(--rule);vertical-align:middle}
#menu .grp a:hover .n{color:var(--secondary)}
#menu .foot{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
  border-top:1px solid var(--rule);padding-top:12px;
  font:var(--t-mono);color:var(--secondary)}

/* A phone has one column and needs to scroll, so the groups stack and the type
   comes down a step. Same page, same order, same numbers. */
@media (max-width:820px){
  #menu .mcols{grid-template-columns:1fr;gap:18px;align-content:start;
    overflow-y:auto;-webkit-overflow-scrolling:touch}
  #menu .grp a{font-size:22px;padding:8px 0}
  /* Two lines of mono under the close button, ending in a hyphenated chassis
     number, is not a header. The description goes; the identity stays. */
  #menu .who .mid{display:none}
  #menu .foot{font-size:10px}
}

/* ------------------------------------------------------- no WebGL, no car
   The register, the timeline, the specification and the archive are the record;
   the model is a way of navigating it. So when the renderer cannot be made, the
   navigation degrades and nothing else does — which is the opposite of what
   used to happen, where a failed context left the loading overlay on screen for
   ever and made every working screen unreachable behind it. */
#stage[data-fallback="true"]{display:none}
/* The car's own controls have nothing to control. Hidden rather than removed:
   the chrome wiring runs afterwards and expects to find them. */
body[data-nogl="true"] #modes,
body[data-nogl="true"] #tools,
body[data-nogl="true"] #tray,
body[data-nogl="true"] #hint,
body[data-nogl="true"] #peek,
body[data-nogl="true"] #timewrap,
body[data-nogl="true"] #assemblies{display:none!important}
#nogl{
  position:fixed;inset:0;z-index:20;overflow-y:auto;
  padding:150px var(--gut) 60px;
  display:flex;flex-direction:column;align-items:center;gap:22px;text-align:center;
}
#nogl figure{margin:0;max-width:min(760px,100%)}
#nogl img{display:block;width:100%;height:auto;border:1px solid var(--rule)}
#nogl figcaption{margin-top:10px;font:var(--t-small);color:var(--secondary);line-height:1.6}
#nogl p{margin:0;max-width:60ch;font:var(--t-small);color:var(--ink-soft);line-height:1.7}
#nogl .acts{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
#nogl .acts a{
  display:inline-flex;align-items:center;min-height:40px;padding:0 16px;
  border:1px solid var(--rule);background:var(--sheet);
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
}
#nogl .acts a:hover{border-color:var(--green);color:var(--green)}
@media(max-width:760px){ #nogl{padding-top:190px} }

/* ------------------------------------------------------------------ canvas */
#stage{position:fixed;inset:0;z-index:0}
#stage canvas{display:block;width:100%;height:100%;touch-action:none}

/* first-visit hint */
/* Part name follows the cursor. It used to be a fourth line of centred type at the
   bottom, stacked on the hint and the anchor note — three captions competing for
   the same 40 px. */
#hoverlab{position:fixed;left:0;top:0;z-index:44;pointer-events:none;white-space:nowrap;
  background:var(--ink);color:var(--studio);border-radius:6px;padding:6px 9px;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  opacity:0;transition:opacity 160ms var(--ease)}
#hoverlab[data-on="true"]{opacity:.94}
#hint{position:fixed;left:50%;bottom:104px;transform:translateX(-50%);z-index:30;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);transition:opacity 700ms var(--ease);pointer-events:none}

/* THE CONTROL DOCK, above 820px, IS NOT THERE. `display:contents` removes the
   box from layout entirely and lets the three groups inside it go on being
   positioned in their own corners exactly as they always have been. It becomes
   a real element only on a phone, where it is one panel. */
#dock{display:contents}

/* ------------------------------------------------------------------- modes */
#modes{position:fixed;left:var(--gut);bottom:30px;z-index:35;
  display:flex;flex-direction:column;gap:7px;align-items:flex-start}
#modes .opts{display:flex;gap:20px}
.cap{font:400 9px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;
  color:var(--secondary);opacity:.75;pointer-events:none}
#modes .opts button{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);position:relative;padding-bottom:6px;
  transition:color var(--t-ui) var(--ease)}
#modes .opts button::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--green);transform:scaleX(0);transform-origin:left;
  transition:transform var(--t-ui) var(--ease)}
#modes .opts button[aria-pressed="true"]{color:var(--green)}
#modes .opts button[aria-pressed="true"]::after{transform:scaleX(1)}
#modes .opts button:hover{color:var(--ink)}

/* ------------------------------------------------------------------- tools */
#tools{position:fixed;right:var(--gut);bottom:34px;z-index:35;display:flex;gap:10px}
#tools button{
  display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);background:rgba(255,255,255,.72);backdrop-filter:blur(8px);
  border:1px solid var(--rule);border-radius:999px;padding:9px 14px;min-height:38px;
  transition:color var(--t-ui) var(--ease),border-color var(--t-ui) var(--ease),
             background var(--t-ui) var(--ease);
}
#tools button:hover{color:var(--ink);border-color:var(--secondary)}
#tools button[aria-pressed="true"]{color:#fff;background:var(--green);border-color:var(--green)}
#tools svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
@media(max-width:760px){
  #tools{bottom:92px;right:var(--gut)}
  #tools button span{display:none}
  #tools button{padding:9px;border-radius:50%;width:38px;justify-content:center}
}

#assemblies{position:fixed;left:var(--gut);bottom:96px;z-index:35;display:flex;gap:14px;flex-wrap:wrap;
  max-width:min(560px,60vw);opacity:0;pointer-events:none;transition:opacity var(--t-ui) var(--ease)}
#assemblies[data-show="true"]{opacity:1;pointer-events:auto}
#assemblies button{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);padding:4px 8px;border:1px solid var(--rule)}
#assemblies button[aria-pressed="true"]{color:var(--ink);border-color:var(--ink)}

/* ---------------------------------------------------------------- timeline */
/* The dates get a segmented pill: one object rather than four loose words, so it
   reads as a single control the way the chip did, while still showing every state
   without a tap first. Its shape also separates it at a glance from the plain-text
   view switcher on the left. */
#timewrap{position:fixed;left:50%;transform:translateX(-50%);bottom:30px;z-index:35;
  display:flex;flex-direction:column;align-items:center;gap:7px}
#timeline{display:flex;background:rgba(255,255,255,.78);backdrop-filter:blur(8px);
  border:1px solid var(--rule);border-radius:999px;padding:3px}
#timeline button{position:relative;padding:8px 15px;border-radius:999px;min-height:32px;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);white-space:nowrap;
  transition:color var(--t-ui) var(--ease),background var(--t-ui) var(--ease)}
#timeline button:hover{color:var(--ink)}
#timeline button[aria-current="true"]{color:#fff;background:var(--green)}

/* Two treatments, both aiming at one calm row along the bottom edge rather than
   the three stacked bands the track-and-dots version produced. */

/* --- 'line': the anchors read exactly like the view modes --- */
#timeline[data-style="line"]{position:fixed;left:0;right:0;bottom:38px;z-index:35;
  display:flex;justify-content:center;gap:26px;pointer-events:none}
#timeline[data-style="line"] button{pointer-events:auto;position:relative;padding-bottom:6px;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);transition:color var(--t-ui) var(--ease)}
#timeline[data-style="line"] button::after{content:'';position:absolute;left:0;right:0;bottom:0;
  height:1px;background:var(--green);transform:scaleX(0);transform-origin:left;
  transition:transform var(--t-ui) var(--ease)}
#timeline[data-style="line"] button:hover{color:var(--ink)}
#timeline[data-style="line"] button[aria-current="true"]{color:var(--green)}
#timeline[data-style="line"] button[aria-current="true"]::after{transform:scaleX(1)}

/* --- 'chip': one word, opening upward --- */
#timeline[data-style="chip"]{position:fixed;left:50%;transform:translateX(-50%);bottom:34px;
  z-index:36;display:flex;flex-direction:column;align-items:center}
#timeline[data-style="chip"] .chip-btn{display:inline-flex;align-items:center;gap:9px;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--green);background:rgba(255,255,255,.78);backdrop-filter:blur(8px);
  border:1px solid var(--rule);border-radius:999px;padding:10px 16px;min-height:38px;
  transition:border-color var(--t-ui) var(--ease)}
#timeline[data-style="chip"] .chip-btn:hover{border-color:var(--secondary)}
#timeline[data-style="chip"] .car{font-size:9px;color:var(--secondary)}
#timeline[data-style="chip"] .pop{position:absolute;bottom:52px;left:50%;
  transform:translateX(-50%) translateY(6px);
  background:var(--sheet);border:1px solid var(--rule);border-radius:12px;
  padding:6px;min-width:210px;opacity:0;pointer-events:none;
  box-shadow:0 12px 34px var(--shadow);
  transition:opacity var(--t-ui) var(--ease),transform var(--t-ui) var(--ease)}
#timeline[data-style="chip"] .pop[data-open="true"]{opacity:1;pointer-events:auto;
  transform:translateX(-50%) translateY(0)}
#timeline[data-style="chip"] .pop button{display:block;width:100%;text-align:left;
  padding:9px 12px;border-radius:8px;transition:background var(--t-ui) var(--ease)}
#timeline[data-style="chip"] .pop button:hover{background:var(--fill)}
#timeline[data-style="chip"] .pop .lb{display:block;font:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;color:var(--secondary)}
#timeline[data-style="chip"] .pop button[aria-current="true"] .lb{color:var(--green)}
#timeline[data-style="chip"] .pop .sub{display:block;font:var(--t-small);
  color:var(--ink-soft);margin-top:2px}

/* ------------------------------------------------------- component peek */
#peek{
  position:fixed;left:var(--gut);bottom:186px;z-index:36;width:min(360px,calc(100% - 2*var(--gut)));
  background:var(--sheet);border:1px solid var(--rule);padding:18px 20px 16px;
  opacity:0;transform:translateY(10px);pointer-events:none;
  transition:opacity var(--t-ui) var(--ease),transform var(--t-ui) var(--ease);
}
#peek[data-open="true"]{opacity:1;transform:none;pointer-events:auto}
#peek h3{font:var(--t-h2);margin:0}
#peek .cid{font:var(--t-mono);color:var(--secondary);margin-top:3px;letter-spacing:.06em}
#peek .chips{display:flex;gap:6px;margin-top:12px;flex-wrap:wrap}
#peek p{font:var(--t-small);color:var(--ink-soft);margin:12px 0 0}
#peek .more{margin-top:16px;font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--green);display:flex;align-items:center;gap:8px}

/* chips */
.chip{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  padding:4px 7px;border:1px solid var(--rule);color:var(--secondary);white-space:nowrap}
.chip[data-tone="status"]{border-color:var(--st-x);border-color:var(--st);color:var(--st-x);color:var(--st)}
.chip[data-tone="ink"]{border-color:var(--ink);color:var(--ink)}

/* ---------------------------------------------------------- record sheet */
#sheet{
  position:fixed;top:0;right:0;width:var(--sheet-w);height:100%;z-index:50;
  background:var(--sheet);border-left:1px solid var(--rule);
  transform:translateX(101%);transition:transform 520ms var(--ease);
  display:flex;flex-direction:column;
}
#sheet[data-open="true"]{transform:none}
#sheet header{padding:30px var(--gut) 18px;border-bottom:1px solid var(--rule-soft);flex:none}
#sheet .back{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);display:flex;gap:8px;align-items:center;margin-bottom:20px}
#sheet .back:hover{color:var(--ink)}
#sheet .cid{font:var(--t-mono);color:var(--secondary);letter-spacing:.06em}
#sheet .plan{display:inline-flex;align-items:center;gap:7px;margin-top:12px;cursor:pointer;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);background:none;border:1px solid var(--rule);border-radius:999px;
  padding:8px 13px;min-height:34px;
  transition:color var(--t-ui) var(--ease),border-color var(--t-ui) var(--ease),
             background var(--t-ui) var(--ease)}
#sheet .plan:hover{color:var(--ink);border-color:var(--secondary)}
#sheet .plan[aria-pressed="true"]{color:#fff;background:var(--green);border-color:var(--green)}
#sheet .plan svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
#sheet h2{font:var(--t-h1);letter-spacing:-0.02em;margin:5px 0 0}
#sheet .body{padding:22px var(--gut) 40px;overflow-y:auto;flex:1}
#sheet .grid{display:grid;grid-template-columns:1fr 1fr;gap:18px 20px}
#sheet .f .label{display:block;margin-bottom:5px}
#sheet .f .v{font:var(--t-body)}
#sheet .prose{font:var(--t-small);color:var(--ink-soft);margin:22px 0 0}
#sheet h4{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);margin:28px 0 10px;font-weight:500}
#sheet .rule{height:1px;background:var(--rule-soft);margin:26px 0 0}

/* status ladder */
.ladder{display:flex;margin-top:10px;border:1px solid var(--rule)}
.ladder span{flex:1;text-align:center;padding:7px 2px;font:8.5px/1.3 var(--mono);
  letter-spacing:.1em;text-transform:uppercase;color:var(--secondary);
  border-right:1px solid var(--rule)}
.ladder span:last-child{border-right:0}
.ladder span[data-on="true"]{background:var(--fill);color:var(--ink);font-weight:600}
.ladder span[data-cur="true"]{background:var(--st,var(--ink));background:var(--st-x);color:#fff;font-weight:600}
@supports (color:oklch(0.5 0.1 20)){ .ladder span[data-cur="true"]{background:var(--st)} }

/* evidence strip */
.ev{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:10px}
.ev figure{margin:0;aspect-ratio:4/3;background:var(--fill);overflow:hidden;position:relative;cursor:pointer}
.ev img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms var(--ease)}
.ev figure:hover img{transform:scale(1.03)}
.ev figure.empty::after{content:'PENDING';position:absolute;inset:0;display:grid;place-items:center;
  font:8px/1 var(--mono);letter-spacing:.14em;color:var(--secondary)}

/* basis note */
.basis{margin-top:14px;padding:10px 12px;background:var(--fill);
  font:var(--t-mono);color:var(--ink-soft);line-height:1.55}

/* ------------------------------------------------------------- documents */
#doc{position:fixed;inset:0;z-index:70;background:var(--studio);overflow-y:auto;
  opacity:0;pointer-events:none;transition:opacity var(--t-ui) var(--ease)}
#doc[data-open="true"]{opacity:1;pointer-events:auto}
#doc .wrap{max-width:920px;margin:0 auto;padding:110px var(--gut) 120px}
#doc h1{font:var(--t-display);letter-spacing:var(--track-display);margin:0 0 8px}
#doc .lede{font:400 clamp(16px,1.7vw,20px)/1.5 var(--sans);color:var(--ink-soft);
  max-width:60ch;margin:0 0 46px}
#doc h3{font:var(--t-h2);margin:44px 0 12px}
#doc p{max-width:68ch;color:var(--ink-soft);margin:0 0 14px}
#doc table{width:100%;border-collapse:collapse;margin-top:14px}
#doc th{text-align:left;font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--secondary);font-weight:500;
  padding:9px 12px 9px 0;border-bottom:1px solid var(--rule)}
#doc td{padding:11px 12px 11px 0;border-bottom:1px solid var(--rule-soft);font:var(--t-small);
  vertical-align:top}
#doc td .sub{display:block;margin-top:4px;color:var(--secondary);font:var(--t-mono);max-width:52ch}

/* TABLES ON A PHONE.
   A three-column table at 390 px gives its third column about four words, and
   the third column is where the prose is. Two different problems, two different
   answers, and getting them the same way round matters:

   · A NUMERIC table is a grid you compare across — the columns are the point.
     Squeezing it destroys the comparison, so it scrolls sideways instead, with
     the row label held still so you never lose which row you are reading.

   · A PROSE table is a set of labelled statements that happen to be laid out
     in columns. Nothing is compared across, so the columns are worth nothing
     and the width is worth everything. Those become cards: each row a block,
     each cell carrying its own label. */
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-top:14px}
.tscroll table{margin-top:0;min-width:520px}

@media(max-width:700px){
  table.stack,table.stack tbody,table.stack tr,table.stack td{
    display:block;width:auto}
  table.stack thead{display:none}
  table.stack tr{border:1px solid var(--rule);padding:13px 14px;margin-bottom:9px}
  table.stack td{padding:0;border:0}
  table.stack td + td{margin-top:8px}
  table.stack td[data-l]::before{
    content:attr(data-l);display:block;margin-bottom:3px;
    font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
    color:var(--secondary)}
  table.stack td .sub{max-width:none}
}
#doc p.src{font:var(--t-mono);color:var(--secondary);margin-top:12px;max-width:68ch}
#doc .close{position:fixed;top:28px;right:var(--gut);font-size:22px;color:var(--secondary);z-index:71}

/* archive grid */
.arch{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px;margin-top:18px}
.arch figure{margin:0;background:var(--sheet);border:1px solid var(--rule);overflow:hidden;cursor:pointer}
.arch .im{aspect-ratio:4/3;background:var(--fill);position:relative;overflow:hidden}
.arch img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 600ms var(--ease)}
.arch figure:hover img{transform:scale(1.03)}
.arch .im.empty::after{content:'NO DERIVATIVE';position:absolute;inset:0;display:grid;place-items:center;
  font:8px/1 var(--mono);letter-spacing:.14em;color:var(--secondary)}
.arch figcaption{padding:9px 11px 11px}
.arch .c1{font:var(--t-small)}
.arch .c2{font:9px/1.4 var(--mono);letter-spacing:.06em;color:var(--secondary);margin-top:4px}

/* filters */
.filters{display:flex;gap:8px;flex-wrap:wrap;margin-top:22px;align-items:center}
.filters input{font:var(--t-body);padding:8px 11px;border:1px solid var(--rule);
  background:var(--sheet);min-width:200px;color:var(--ink)}
.filters button{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  padding:6px 9px;border:1px solid var(--rule);color:var(--secondary)}
.filters button[aria-pressed="true"]{color:var(--ink);border-color:var(--ink)}

/* ------------------------------------------------------- parts grid */
.viewtog{display:flex;gap:0;margin-left:auto}
.viewtog button{display:inline-flex;align-items:center;gap:6px;cursor:pointer;background:none;
  border:1px solid var(--rule);padding:8px 12px;min-height:36px}
.viewtog button:first-child{border-radius:8px 0 0 8px}
.viewtog button:last-child{border-radius:0 8px 8px 0;border-left:0}
.viewtog button[aria-pressed="true"]{color:#fff;background:var(--green);border-color:var(--green)}
.viewtog svg{width:13px;height:13px;fill:currentColor;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round}
.viewtog button[data-view="list"] svg{fill:none}
#doc p.count{font:var(--t-mono);color:var(--secondary);margin:14px 0 0}

.pgrid{display:grid;gap:14px;margin-top:18px;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.pcard{display:flex;flex-direction:column;gap:0;text-align:left;cursor:pointer;position:relative;
  background:var(--sheet);border:1px solid var(--rule);border-radius:12px;overflow:hidden;
  transition:border-color var(--t-ui) var(--ease),transform var(--t-ui) var(--ease)}
.pcard:hover{border-color:var(--secondary);transform:translateY(-2px)}
.pcard .im{position:relative;display:block;aspect-ratio:4/3;background:var(--studio);
  border-bottom:1px solid var(--rule-soft)}
.pcard .im img{width:100%;height:100%;object-fit:contain;display:block}
.pcard .im .ph{display:none;position:absolute;inset:0;place-items:center;text-align:center;
  padding:0 14px;font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary)}
.pcard .im[data-missing="true"] img{display:none}
.pcard .im[data-missing="true"] .ph{display:grid}
.pcard .meta{display:block;padding:11px 13px 13px}
.pcard .meta .id{display:block;font:var(--t-mono);color:var(--secondary);letter-spacing:.05em}
.pcard .meta .nm{display:block;font:500 14px/1.3 var(--sans);margin-top:3px}
.pcard .meta .as{display:block;font:var(--t-small);color:var(--secondary);margin-top:4px}
@media(max-width:820px){
  .pgrid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}
  .viewtog{margin-left:0}
}

/* timeline list (accessible route) */
.tl-list{margin-top:26px;border-top:1px solid var(--rule)}
.tl-row{display:grid;grid-template-columns:112px 1fr auto;gap:18px;padding:16px 0;
  border-bottom:1px solid var(--rule-soft);align-items:start;width:100%;text-align:left}
.tl-row:hover{background:var(--sheet)}
.tl-row .d{font:var(--t-mono);color:var(--secondary);letter-spacing:.04em}
.tl-row .t{font:var(--t-h2)}
.tl-row .n{font:var(--t-small);color:var(--ink-soft);margin-top:4px;max-width:64ch}
.tl-row .c{font:9px/1 var(--mono);letter-spacing:.1em;color:var(--secondary);white-space:nowrap;padding-top:4px}

/* component navigator (non-3D route, a11y requirement) */
.nav-list{margin-top:20px;border-top:1px solid var(--rule)}
.nav-row{display:grid;grid-template-columns:132px 1fr 130px 92px;gap:14px;align-items:center;
  padding:11px 0;border-bottom:1px solid var(--rule-soft);width:100%;text-align:left}
.nav-row:hover{background:var(--sheet)}
.nav-row .id{font:var(--t-mono);color:var(--secondary);letter-spacing:.04em}
.nav-row .nm{font:var(--t-small)}
.nav-row .as{font:9px/1 var(--mono);letter-spacing:.09em;color:var(--secondary)}

/* loading */
#boot{position:fixed;inset:0;z-index:90;background:var(--studio);
  display:grid;place-items:center;transition:opacity 600ms var(--ease)}
/* On its way out it stops taking taps immediately, rather than when the
   removal timer eventually runs. See boot() in app.js. */
#boot[data-out="true"]{pointer-events:none}
#boot .bwrap{display:flex;flex-direction:column;align-items:center;text-align:center}
#boot .kick{font:500 10px/1 var(--display);letter-spacing:.34em;text-transform:uppercase;
  color:var(--secondary);padding-left:.34em;
  animation:bootin 700ms var(--ease) both}
#boot .num{font:600 clamp(54px,7vw,86px)/0.95 var(--display);letter-spacing:-0.01em;
  color:var(--green);margin-top:2px;
  animation:bootin 700ms 60ms var(--ease) both}
#boot .b{width:190px;height:2px;background:var(--rule);position:relative;overflow:hidden;
  margin-top:26px;border-radius:2px;
  animation:bootin 700ms 140ms var(--ease) both}
#boot .b i{position:absolute;inset:0;background:var(--green);transform:scaleX(0);
  transform-origin:left;transition:transform 520ms var(--ease);border-radius:2px}
/* no Content-Length: sweep instead of pretending to know how far along we are */
#boot .b[data-indeterminate] i{transform:none;width:38%;animation:bootsweep 1.25s var(--ease) infinite}
@keyframes bootsweep{0%{left:-38%}100%{left:100%}}
#boot .t{margin-top:18px;font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--secondary);
  animation:bootin 700ms 200ms var(--ease) both}
#boot .pc{margin-top:7px;font:var(--t-mono);color:var(--secondary);opacity:.75;
  font-variant-numeric:tabular-nums;
  animation:bootin 700ms 240ms var(--ease) both}
/* the hatch drifts slowly behind it — the same technical motif as the header */
#boot::after{content:'';position:absolute;left:0;right:0;bottom:0;height:120px;
  background:repeating-linear-gradient(115deg,var(--rule) 0 1px,transparent 1px 11px);
  -webkit-mask-image:linear-gradient(to top,#000,transparent);
          mask-image:linear-gradient(to top,#000,transparent);
  opacity:.5;animation:bootdrift 9s linear infinite}
@keyframes bootin{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@keyframes bootdrift{from{background-position:0 0}to{background-position:120px 0}}
@media (prefers-reduced-motion:reduce){
  #boot .kick,#boot .num,#boot .b,#boot .t,#boot .pc{animation:none}
  #boot .b[data-indeterminate] i{animation:none;width:100%;left:0;opacity:.35}
  #boot::after{animation:none}
}

/* lightbox */
#lb{position:fixed;inset:0;z-index:95;background:rgba(247,245,242,.97);
  display:grid;place-items:center;opacity:0;pointer-events:none;
  transition:opacity var(--t-ui) var(--ease);padding:var(--gut)}
#lb[data-open="true"]{opacity:1;pointer-events:auto}
#lb img{max-width:min(1200px,92vw);max-height:82vh;object-fit:contain;display:block}
#lb .cap{position:fixed;bottom:34px;left:50%;transform:translateX(-50%);
  font:var(--t-mono);color:var(--secondary);text-align:center}
#lb .close{position:fixed;top:28px;right:var(--gut);font-size:22px;color:var(--secondary)}

/* ------------------------------------------------------------ responsive */
@media (max-width: 820px){
  #identity{top:14px;flex-direction:column;gap:2px}
  #identity .mark{font-size:40px;line-height:1}
  #identity .who .d{display:none}
  /* The centred lockup owns the top of a narrow screen, so the section links
     collapse into Info — which is also how the design reference reads. */
  #topbar{top:16px;gap:0}
  #topbar button{font-size:9px;letter-spacing:.12em}
  #topbar button:not([data-doc="menu"]){display:none}
  #hint{bottom:150px;font-size:8.5px;white-space:nowrap}
  #stage{bottom:0}
  #modes .opts{gap:16px}
  #timeline button{padding:8px 11px}
  #assemblies{display:none}

  /* THE HANDLE. Fixed to the visible bottom edge of the window, and raised by
     the panel's measured height when the panel is up — see the note in
     index.html for the two ways this went wrong before. Shut is still the
     default: the first thing a phone should show is the car, not the machinery
     for looking at it. And it states what is currently on screen, so collapsing
     the controls never costs the answer to "what am I looking at" — only the
     ability to change it, one tap away.

     A PILL, NOT A BAR. A hard-edged white band pinned across the full width
     reads as a control belonging to the phone rather than to this page, and it
     drew a line under the car the composition never asked for. */
  #tray{
    display:inline-flex;align-items:center;gap:11px;
    position:fixed;left:50%;z-index:39;
    bottom:calc(18px + env(safe-area-inset-bottom) + var(--dockh, 0px));
    transform:translateX(-50%);
    max-width:calc(100% - 2*var(--gut));
    min-height:var(--tap);padding:0 8px 0 18px;
    background:var(--sheet);border:1px solid var(--rule);border-radius:999px;
    font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
    color:var(--ink);box-shadow:0 3px 18px var(--shadow);
    transition:bottom var(--t-ui) var(--ease);
    touch-action:none;                       /* the drag below is ours, not the page's */
  }
  #tray .t{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* The chevron sits in a disc of its own, so the handle reads as a control
     with a hit target rather than as a label with a mark after it. */
  #tray .h{
    flex:none;width:26px;height:26px;border-radius:50%;background:var(--paper);
    position:relative;
  }
  #tray .h::after{
    content:'';position:absolute;left:50%;top:50%;width:8px;height:8px;
    border-right:1.4px solid var(--secondary);border-bottom:1.4px solid var(--secondary);
    transform:translate(-50%,-70%) rotate(-135deg);
    transition:transform var(--t-ui) var(--ease);
  }
  /* Open, it points the way it will go: down. And it can be taken there — the
     chevron is a promise the panel now keeps, because it can be dragged. */
  #tray[aria-expanded="true"] .h::after{transform:translate(-50%,-30%) rotate(45deg)}
  /* While a finger is on it, nothing eases: the panel goes where the finger is. */
  body[data-dragging="true"] #tray,
  body[data-dragging="true"] #dock{transition:none}

  /* THE DOCK. One panel, and the controls inside it stack themselves.
     Everything here used to be three fixed elements pushed past each other by
     hard-coded bottom offsets that had to be kept in agreement by hand — and
     were not: Maintenance grew a legend and the row above it stayed put. */
  #dock{
    position:fixed;left:0;right:0;bottom:0;z-index:38;
    display:flex;flex-direction:column;gap:20px;
    padding:14px var(--gut) calc(20px + env(safe-area-inset-bottom));
    border-radius:18px 18px 0 0;
    /* Down is all the way down. The handle is a separate, pinned element —
       see the note in index.html. */
    transform:translateY(100%);
    transition:transform var(--t-ui) var(--ease);
  }
  /* Shut, the panel is only its handle, so it must not paint a card behind the
     car — that white band across the foot of the screen is the thing this was
     rebuilt to get rid of. The card arrives with the contents. */
  body[data-tray="open"] #dock{
    background:var(--sheet);border-top:1px solid var(--rule);
    box-shadow:0 -6px 26px var(--shadow);
    padding-top:26px;
  }
  /* Below the fold is not the same as absent: a control translated off the
     screen is still in the tab order and still takes a tap through the glass.
     The visibility change waits for the slide out and leads the slide in, so
     neither direction flickers. */
  #dock{visibility:hidden;transition:transform var(--t-ui) var(--ease),
                                     visibility 0s linear var(--t-ui)}
  body[data-tray="open"] #dock{transform:none;visibility:visible;
    transition:transform var(--t-ui) var(--ease), visibility 0s linear 0s}
  #dock > *{position:static;left:auto;right:auto;bottom:auto;transform:none}
  #modes{display:flex;flex-direction:column;align-items:flex-start;gap:9px}
  /* The panel has a header row: the rail in the middle of it, Recentre at the
     end of it, and the controls proper below. Sharing a line with the view
     labels put a 36px pill through a 12px row and the two boxes overlapped by
     four pixels — invisible, and exactly the class of fault this whole panel
     exists to make impossible. */
  #tools{align-self:flex-end;margin-top:-8px;gap:8px}
  /* In the panel there is room for the word, and a lone circle with a cross in
     it is a rebus. Off the car it was icon-only because it sat ON the car. */
  #tools button{border-radius:999px;width:auto;padding:0 14px;min-height:36px}
  #tools button span{display:inline}
  #timewrap{display:flex;flex-direction:column;align-items:center;gap:10px;width:100%}
  /* The caption is a sentence in Maintenance rather than two words, and a
     sentence set flush left under centred controls reads as a different
     column. */
  #timewrap .cap{text-align:center;max-width:34ch}
  /* Nothing in the panel may be wider than the panel. */
  #dock #timeline,#dock #horizon{max-width:100%}

  /* The hint belongs to the car, and the panel covers the car. It also used to
     be shown only while the panel was OPEN — the exact inverse of what was
     meant — which is how it came to be printed across the view buttons. */
  body[data-tray="open"] #hint,
  body[data-tray="open"] #ctx{opacity:0;pointer-events:none}

  /* The peek card is full-width at the foot of the screen and would otherwise
     bury the handle. It keeps a band clear rather than the handle moving,
     because a control that changes position while you are reaching for it is
     worse than one that is slightly further down. */
  #peek{left:0;right:0;bottom:0;width:100%;border:0;border-top:1px solid var(--rule);
    padding:16px var(--gut) 78px;transform:translateY(100%)}
  #peek[data-open="true"]{transform:none}
  #sheet{width:100%;transform:translateY(101%);border-left:0;border-top:1px solid var(--rule)}
  #sheet[data-open="true"]{transform:none}
  #doc .wrap{padding:96px var(--gut) 90px}
  .nav-row{grid-template-columns:1fr;gap:3px}
  .nav-row .id{font-size:10px}
  .tl-row{grid-template-columns:1fr;gap:4px}
}

/* ====================================================== a phone, held sideways
   844 x 390 is WIDER than the phone breakpoint and shorter than anything the
   wide composition assumes, so it was served the desktop layout in a third of
   the height. Every element that the desktop puts in a corner arrived in the
   middle: the hatch — pinned at top:210px — cut across the car, the view
   buttons printed over the timeline ticks, and the context line sat on the
   bonnet. The breakpoint asked about width and the problem was height.

   THE GATE IS COARSE-POINTER, DELIBERATELY. A short browser window on a laptop
   is a window somebody chose, and telling them to rotate their desk would be
   absurd. This asks only where there is something to rotate. */
#rotate{display:none}

/* The 3D context, taken away by the browser. Nothing else on the page is
   affected, so this covers the stage and leaves the record reachable. */
#gllost{display:none}
body[data-gl="lost"] #gllost{
  display:flex;flex-direction:column;align-items:center;gap:14px;
  position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);z-index:52;
  max-width:min(46ch,86vw);padding:26px 28px;text-align:center;
  background:var(--sheet);border:1px solid var(--rule);box-shadow:0 6px 30px var(--shadow);
}
body[data-gl="lost"] #gllost p{margin:0;font:var(--t-small);line-height:1.6;color:var(--ink-soft)}
body[data-gl="lost"] #gllost button{
  min-height:var(--tap);padding:0 18px;border:1px solid var(--green);border-radius:999px;
  background:var(--green);color:#fff;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
}
/* The frozen frame is not the car, so it should not be presented as it. */
body[data-gl="lost"] #stage{opacity:.25;filter:saturate(.2)}
body[data-gl="lost"] #hint,body[data-gl="lost"] #ctx{display:none}

@media (orientation:landscape) and (max-height:500px) and (pointer:coarse){
  /* Nothing underneath may collide, whether or not the panel is up. */
  #ctx,#hint,#tray,#dock,#landing,#assemblies{display:none!important}
  /* ABOVE THE SCRIM, BOTH OF THEM. The panel is z-55 and the navigation was
     z-40, which left the burger visible, blurred, and impossible to press —
     the one control that reaches everything this panel is pointing at. */
  #identity,#topbar{z-index:56}
  #identity{top:10px;left:var(--gut);right:auto;align-items:flex-start;text-align:left}
  #identity .lockup{flex-direction:row;align-items:baseline;gap:9px}
  #identity .mark{font-size:26px}
  #identity .who{position:static;text-align:left;margin-top:2px}
  #topbar{top:10px}

  #rotate{
    display:flex;position:fixed;inset:0;z-index:55;
    align-items:center;justify-content:center;
    padding:20px calc(var(--gut) + env(safe-area-inset-left))
            20px calc(var(--gut) + env(safe-area-inset-right));
    /* A scrim, not a wall. The car is still turning behind it, which is the
       whole argument for turning the phone back. */
    background:rgba(247,245,242,.88);
    -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  }
  /* A document screen is the one thing that reads perfectly at this size, so
     opening one takes this panel off the screen and closing it brings it back.
     Sibling selector, no JavaScript, no state to keep in agreement. */
  #doc[data-open="true"] ~ #rotate{display:none}

  #rotate .rwrap{max-width:62ch;text-align:center}
  #rotate .ric{width:30px;height:30px;fill:none;stroke:var(--green);
    stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
  #rotate .rt{margin:8px 0 0;font:600 21px/1.15 var(--display);letter-spacing:-0.02em;
    color:var(--ink)}
  /* One line, and it shrinks rather than wraps: a caption that breaks mid-
     clause on a panel this small reads as a paragraph. */
  #rotate .rs{margin:7px auto 0;max-width:none;white-space:nowrap;
    font:400 clamp(11px,1.7vw,15px)/1.5 var(--sans);color:var(--ink-soft)}
  #rotate .rlinks{
    margin-top:14px;display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
  }
  #rotate .rlinks a{
    display:inline-flex;align-items:center;min-height:34px;padding:0 13px;
    border:1px solid var(--rule);background:var(--sheet);border-radius:999px;
    font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
    color:var(--ink);
  }
  #rotate .rlinks a:hover{border-color:var(--green);color:var(--green)}
  #rotate .rn{margin:11px 0 0;font:var(--t-mono);color:var(--secondary)}
}

/* ----------------------------------------------------------------- the plan
   Ten stage cards. The one the car is in carries the accent and says so in
   words as well — a colour alone is a code the reader has to learn, and this
   page is read once by people who will not learn it. */
.ph-cards{display:grid;gap:14px;margin-top:26px}
.ph-card{
  border:1px solid var(--rule);border-left:3px solid var(--rule);
  padding:18px 20px;background:var(--sheet);
}
.ph-card[data-state="active"]{border-left-color:var(--a-repair)}
.ph-card[data-state="finished"]{border-left-color:var(--a-complete)}
.ph-card[data-current="true"]{border-color:var(--green);border-left-color:var(--green)}
.ph-n{display:flex;flex-wrap:wrap;gap:10px;align-items:baseline;margin-bottom:6px}
.ph-n .num{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary)}
.ph-n .now{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:#fff;background:var(--green);padding:3px 8px}
.ph-n .stop{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--a-warn);border:1px solid var(--a-warn);padding:2px 7px}
.ph-card h3{margin:0 0 8px;font:var(--t-h2)}
.ph-card .aim{margin:0 0 14px;font:var(--t-small);color:var(--ink-soft);
  line-height:1.65;max-width:70ch}
/* Entry and exit are the two judgements that make a stage a stage rather than
   a heading, so they get the structure of a definition list and not a
   paragraph. */
.ph-gates{margin:0 0 14px;display:grid;grid-template-columns:170px 1fr;gap:6px 16px}
.ph-gates dt{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary)}
.ph-gates dd{margin:0;font:var(--t-small);color:var(--ink-soft);line-height:1.6}
.ph-bar{height:4px;background:var(--rule-soft);overflow:hidden;margin-bottom:7px}
.ph-bar i{display:block;height:100%;background:var(--a-complete)}
.ph-count{margin:0;font:var(--t-mono);color:var(--secondary)}
@media(max-width:700px){
  .ph-gates{grid-template-columns:1fr;gap:3px 0}
  .ph-gates dd{margin-bottom:8px}
  .ph-card{padding:15px 16px}
}

/* ------------------------------------------------------- service & life
   The forward-looking screen. Status is carried by the same four accents the
   component ladder already uses, so "overdue" here and "replace" there read as
   the same register of concern rather than as two invented colour systems. */
.sv-head{margin-top:22px}
.sv-chips{display:flex;gap:8px;flex-wrap:wrap}
.sv-chip{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  padding:6px 10px;border:1px solid var(--rule);border-radius:999px;color:var(--secondary)}
.sv-chip[data-tone="replace"]  {border-color:var(--a-replace-x);border-color:var(--a-replace);
                                color:var(--a-replace-x);color:var(--a-replace)}
.sv-chip[data-tone="repair"]   {border-color:var(--a-repair-x);border-color:var(--a-repair);
                                color:var(--a-repair-x);color:var(--a-repair)}
.sv-chip[data-tone="complete"] {border-color:var(--a-complete-x);border-color:var(--a-complete);
                                color:var(--a-complete-x);color:var(--a-complete)}
.sv-chip[data-tone="reference"]{border-color:var(--a-reference-x);border-color:var(--a-reference);
                                color:var(--a-reference-x);color:var(--a-reference)}

/* Which authority a figure rests on, said next to the figure. The accent is
   the same one the register uses for a reference source, because that is what
   this is: a statement about where a number came from. */
/* What is fitted, on a component's record. The one on the car carries the
   accent; the ones that came off recede without vanishing. */
.fitrow{display:grid;gap:2px;padding:10px 0;border-bottom:1px solid var(--rule-soft)}
.fitrow[data-on="true"]{border-left:2px solid var(--a-complete);padding-left:10px}
.fitrow .w{font:var(--t-small);color:var(--ink)}
.fitrow .w code{font:var(--t-mono);color:var(--secondary)}
.fitrow .d{font:var(--t-mono);color:var(--secondary)}
.fitrow .l{font:var(--t-small);color:var(--ink-soft);margin-top:3px}
.fitrow[data-on="false"]{opacity:.7}

.sv-gov{border-left:2px solid var(--rule);padding-left:8px;margin-top:4px!important}
.sv-gov[data-by="part"]{border-left-color:var(--a-reference);color:var(--ink-soft)}

.sv-row .d{font:500 11.5px/1.45 var(--mono);letter-spacing:.04em}
.sv-row[data-st="overdue"]       .d{color:var(--a-replace-x);color:var(--a-replace)}
.sv-row[data-st="due-soon"]      .d{color:var(--a-repair-x);color:var(--a-repair)}
.sv-row[data-st="commissioning"] .d{color:var(--a-reference-x);color:var(--a-reference)}
.sv-row[data-st="scheduled"]     .d{color:var(--a-complete-x);color:var(--a-complete)}
/* A coloured left edge so a long list can be scanned without reading it */
.sv-row{position:relative;padding-left:14px}
.sv-row::before{content:"";position:absolute;left:0;top:16px;bottom:16px;width:2px;background:var(--rule)}
.sv-row[data-st="overdue"]::before      {background:var(--a-replace-x);background:var(--a-replace)}
.sv-row[data-st="due-soon"]::before     {background:var(--a-repair-x);background:var(--a-repair)}
.sv-row[data-st="commissioning"]::before{background:var(--a-reference-x);background:var(--a-reference)}
.sv-row[data-st="scheduled"]::before    {background:var(--a-complete-x);background:var(--a-complete)}
.sv-meta{display:block;font:var(--t-mono);color:var(--secondary);margin-top:5px}
.sv-note{display:block;font:var(--t-small);color:var(--ink-soft);margin-top:6px;max-width:62ch;
  padding-left:10px;border-left:1px solid var(--rule-soft)}

/* the same item, inside a component record */
.sv-mini{padding:11px 0 11px 12px;border-bottom:1px solid var(--rule-soft);position:relative}
.sv-mini::before{content:"";position:absolute;left:0;top:12px;bottom:12px;width:2px;background:var(--rule)}
.sv-mini[data-st="overdue"]::before      {background:var(--a-replace-x);background:var(--a-replace)}
.sv-mini[data-st="due-soon"]::before     {background:var(--a-repair-x);background:var(--a-repair)}
.sv-mini[data-st="commissioning"]::before{background:var(--a-reference-x);background:var(--a-reference)}
.sv-mini[data-st="scheduled"]::before    {background:var(--a-complete-x);background:var(--a-complete)}
.sv-mini-h{display:flex;justify-content:space-between;gap:12px;align-items:baseline}
.sv-mini-h .t{font:var(--t-small);color:var(--ink)}
.sv-mini-h .s{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);white-space:nowrap}
.sv-mini[data-st="overdue"]  .sv-mini-h .s{color:var(--a-replace-x);color:var(--a-replace)}
.sv-mini[data-st="due-soon"] .sv-mini-h .s{color:var(--a-repair-x);color:var(--a-repair)}
.sv-mini .n{font:var(--t-mono);color:var(--secondary);margin-top:4px}

/* a flag on the parts grid, for components carrying something overdue or due */
.pcard .sv-flag{position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;
  background:var(--a-repair-x);background:var(--a-repair)}
.pcard .sv-flag[data-st="overdue"]{background:var(--a-replace-x);background:var(--a-replace)}
/* the item name is a heading, not a lead-in to the sentence after it */
.sv-row .t{display:block}
.sv-row .n{display:block}

/* ------------------------------------------------------- service on the car
   The horizon replaces the timeline pill rather than sitting beside it. They are
   the same control pointed in opposite directions and there is never a reason to
   want both at once. */
#horizon{width:min(520px,72vw);margin-top:10px}
#horizon input[type=range]{
  -webkit-appearance:none;appearance:none;width:100%;height:22px;background:none;cursor:pointer;display:block}
#horizon input[type=range]::-webkit-slider-runnable-track{
  height:2px;background:var(--rule);border-radius:2px}
#horizon input[type=range]::-moz-range-track{height:2px;background:var(--rule);border-radius:2px}
#horizon input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:15px;height:15px;border-radius:50%;
  background:var(--green);border:2px solid var(--studio);margin-top:-6.5px;
  box-shadow:0 1px 5px var(--shadow)}
#horizon input[type=range]::-moz-range-thumb{width:15px;height:15px;border-radius:50%;
  background:var(--green);border:2px solid var(--studio);box-shadow:0 1px 5px var(--shadow)}
#horizon .hticks{display:flex;justify-content:space-between;margin-top:2px}
#horizon .hticks span{font:400 9px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--secondary);opacity:.7}

#svleg{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-bottom:9px}
#svleg span{display:inline-flex;align-items:center;gap:6px;
  font:400 9px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--secondary)}
#svleg i{width:7px;height:7px;border-radius:50%;display:block}
#svleg [data-st="overdue"]       i{background:var(--a-replace-x);background:var(--a-replace)}
#svleg [data-st="due-soon"]      i{background:var(--a-repair-x);background:var(--a-repair)}
#svleg [data-st="commissioning"] i{background:var(--a-reference-x);background:var(--a-reference)}
#svleg [data-st="scheduled"]     i{background:var(--a-complete-x);background:var(--a-complete)}
#svleg b{color:var(--ink);font-weight:500}

/* service items inside the collapsed peek */
#peek .svp{margin-top:12px;border-top:1px solid var(--rule-soft);padding-top:10px}
#peek .svp div{display:flex;justify-content:space-between;gap:10px;padding:3px 0;
  font:var(--t-mono);color:var(--secondary)}
#peek .svp div b{font-weight:400;color:var(--ink)}
#peek .svp [data-st="overdue"]  b{color:var(--a-replace-x);color:var(--a-replace)}
#peek .svp [data-st="due-soon"] b{color:var(--a-repair-x);color:var(--a-repair)}
@media(max-width:760px){
  #horizon{width:min(420px,86vw)}
  #svleg{gap:9px}
}
.rhythm{margin-top:18px;background:var(--sheet);border:1px solid var(--rule);
  border-radius:12px;padding:18px 16px;overflow-x:auto}
.rhythm svg{min-width:720px;display:block}

/* ------------------------------------------------- bottom bar, tightened
   #timewrap is a centred flex column, so its box is as wide as its widest child
   — which since the horizon arrived is most of a phone screen. It was silently
   swallowing clicks meant for the view switcher underneath it. Only the controls
   inside it should take a pointer at all. */
#timewrap{pointer-events:none}
#timewrap #timeline,#timewrap #horizon,#timewrap #horizon input{pointer-events:auto}

/* The five hard-coded bottom offsets that used to live here — 66px, 148px,
   202px and two more — are gone with the dock. They were an attempt to stack
   three independently-positioned fixed elements by arithmetic, and arithmetic
   that has to be right in five places is arithmetic that will be wrong in one:
   Maintenance added a legend, the row above it did not move, and the view
   buttons printed straight over the hint. Boxes stack themselves. */
@media(max-width:760px){
  #modes .opts{gap:15px;flex-wrap:wrap}
}

/* ------------------------------------------------- service · stats + planner
   The screen used to open with an admin table, which is a dull way into
   something that is meant to feel like a tool. It opens on numbers and a
   control now, and the record-keeping has moved to the bottom where it belongs. */
.sv-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);border-radius:12px;overflow:hidden;
  margin:26px 0 30px}
.sv-stats .st{background:var(--sheet);padding:18px 16px 16px}
.sv-stats .st b{display:block;font:500 clamp(26px,3.2vw,38px)/1 var(--sans);
  letter-spacing:-.03em;color:var(--green)}
.sv-stats .st span{display:block;font:var(--t-small);color:var(--ink);margin-top:7px}
.sv-stats .st i{display:block;font:var(--t-mono);color:var(--secondary);font-style:normal;margin-top:3px}

.planner{background:var(--sheet);border:1px solid var(--rule);border-radius:14px;
  padding:22px 20px;margin:8px 0 34px}
.pl-lede{font:var(--t-small);color:var(--ink-soft);max-width:70ch;margin:8px 0 0}
.pl-fields{display:flex;gap:22px;flex-wrap:wrap;align-items:flex-end;margin-top:20px}
.pl-f{display:flex;flex-direction:column;gap:6px}
.pl-f input{font:500 22px/1 var(--sans);letter-spacing:-.02em;color:var(--ink);
  background:none;border:0;border-bottom:1.5px solid var(--rule);padding:6px 2px;width:130px}
.pl-f input:focus{outline:none;border-bottom-color:var(--green)}
.pl-rate{display:flex;align-items:baseline;gap:8px;padding-bottom:8px}
.pl-rate b{font:500 22px/1 var(--sans);letter-spacing:-.02em;color:var(--green)}
.pl-rate span:last-child{font:var(--t-small);color:var(--ink-soft)}

.pl-slide{-webkit-appearance:none;appearance:none;width:100%;height:22px;background:none;
  cursor:pointer;display:block;margin-top:20px}
.pl-slide::-webkit-slider-runnable-track{height:2px;background:var(--rule);border-radius:2px}
.pl-slide::-moz-range-track{height:2px;background:var(--rule);border-radius:2px}
.pl-slide::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;
  border-radius:50%;background:var(--green);border:2px solid var(--sheet);margin-top:-7px;
  box-shadow:0 1px 5px var(--shadow)}
.pl-slide::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--green);
  border:2px solid var(--sheet);box-shadow:0 1px 5px var(--shadow)}
.pl-ticks{display:flex;justify-content:space-between;margin-top:2px}
.pl-ticks span{font:400 9px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--secondary);opacity:.75}

.pl-body{margin-top:22px}
.dp-block{margin-bottom:20px}
.dp-h{display:flex;justify-content:space-between;align-items:baseline;
  border-bottom:1px solid var(--rule);padding-bottom:6px}
.dp-h span{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--secondary)}
.dp-h b{font:500 17px/1 var(--sans);color:var(--ink)}
.dp-n{font:var(--t-mono);color:var(--secondary);margin:6px 0 4px}
.dp-row{display:grid;grid-template-columns:10px 1fr auto auto;gap:12px;align-items:baseline;
  width:100%;text-align:left;padding:8px 0;border-bottom:1px solid var(--rule-soft);cursor:pointer}
.dp-row:hover{background:var(--fill)}
.dp-row .dot{width:7px;height:7px;border-radius:50%;align-self:center}
.dp-row .nm{font:var(--t-small);color:var(--ink)}
.dp-row .by{font:var(--t-mono);color:var(--secondary)}
.dp-row .wh{font:500 11.5px/1.45 var(--mono);color:var(--ink);white-space:nowrap}
.dp-foot{font:var(--t-mono);color:var(--secondary);padding-top:6px;border-top:1px solid var(--rule)}

/* chart hover */
.rhythm{position:relative}
.rhythm .rw{cursor:crosshair}
.rtip{position:absolute;z-index:6;pointer-events:none;max-width:280px;
  background:var(--ink);color:var(--studio);border-radius:8px;padding:10px 12px;
  box-shadow:0 6px 24px rgba(27,26,24,.22)}
.rtip b{font:500 13px/1.25 var(--sans);display:block}
.rtip .k{font:var(--t-small);opacity:.82;margin-top:4px}
.rtip .m{font:400 10.5px/1.5 var(--mono);opacity:.72;margin-top:5px}
.rtip .p{font:400 10.5px/1.5 var(--mono);opacity:.9;margin-top:6px;padding-top:6px;
  border-top:1px solid rgba(247,245,242,.2)}

/* the clock sub-headings inside a long status group */
.sv-sub{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary);margin:26px 0 0;padding-left:10px;border-left:2px solid var(--rule)}
.sv-parts{display:block;font:var(--t-mono);color:var(--secondary);margin-top:4px}

@media(max-width:760px){
  .pl-fields{gap:14px}
  .pl-f input{width:110px;font-size:19px}
  .dp-row{grid-template-columns:10px 1fr auto;row-gap:2px}
  .dp-row .by{grid-column:2/4;font-size:10px}
}

/* ------------------------------------------------- geometry provenance
   Per part, on its own record: is this shape 118, or a 1985 car standing in
   for it? The distinction the whole model rests on, so it gets a colour. */
.geo{padding:11px 13px;border-radius:8px;border:1px solid var(--rule);
  border-left-width:3px;background:var(--fill);margin-top:4px}
.geo b{display:block;font:var(--t-h2);margin-bottom:5px}
.geo span{display:block;font:var(--t-small);color:var(--ink-soft);max-width:62ch}
.geo code{font:var(--t-mono)}
.geo[data-src="built"]{border-left-color:var(--a-complete-x);border-left-color:var(--a-complete)}
.geo[data-src="built"] b{color:var(--a-complete-x);color:var(--a-complete)}
.geo[data-src="donor"]{border-left-color:var(--a-repair-x);border-left-color:var(--a-repair)}
.geo[data-src="donor"] b{color:var(--a-repair-x);color:var(--a-repair)}
.geo[data-src="none"]{border-left-color:var(--rule)}
.geo[data-src="none"] b{color:var(--secondary)}

/* ---------------------------------------------------- parts catalogue block
   Identity, not shape. Part number set in mono on the left so the numbers form
   a column the eye can run down — which is how you actually use a catalogue. */
.cat{padding:11px 13px;border-radius:8px;border:1px solid var(--rule);
  border-left-width:3px;background:var(--fill);margin-top:4px}
.cat .row{display:grid;grid-template-columns:76px 1fr;gap:12px;
  padding:6px 0;border-bottom:1px solid var(--rule-soft)}
.cat .row:last-of-type{border-bottom:0}
.cat .pn{font:var(--t-mono);color:var(--ink)}
.cat .pnm{font:var(--t-small);color:var(--ink-soft);max-width:56ch}
.cat .pnm em{font-style:normal;color:var(--secondary)}
.cat .ct{color:var(--secondary)}
.cat .pnn{display:block;color:var(--secondary);margin-top:3px}
.cat .meta{display:flex;gap:10px;align-items:center;margin-top:9px;
  font:var(--t-mono);color:var(--secondary)}
.cat .meta .m{margin-left:auto;text-transform:uppercase;letter-spacing:.06em}
.cat .into{font:var(--t-small);color:var(--ink-soft);margin-top:7px}
.cat .cnote{font:var(--t-small);color:var(--ink-soft);max-width:62ch;margin-top:7px}
.cat .cnote.quiet{color:var(--secondary)}
.cat[data-match="confirmed"]{border-left-color:var(--a-complete)}
.cat[data-match="confirmed"] .meta .m{color:var(--a-complete)}
.cat[data-match="probable"]{border-left-color:var(--a-repair)}
.cat[data-match="probable"] .meta .m{color:var(--a-repair)}
.cat[data-match="uncertain"]{border-left-color:var(--rule)}

/* ------------------------------------------------------------- corrections
   The archive showing its own edits. Struck-through on the left, the figure
   that replaced it on the right, and the document that forced the change. */
.corr{padding:12px 0;border-bottom:1px solid var(--rule-soft)}
.corr:last-child{border-bottom:0}
.corr .meta{font:var(--t-mono);color:var(--secondary)}
.corr .swap{font:var(--t-small);margin-top:5px}
.corr .swap s{color:var(--secondary)}
.corr .swap .ar{color:var(--secondary);margin:0 4px}
.corr .swap b{color:var(--ink)}
.corr .ids{font:var(--t-mono);color:var(--secondary);margin-top:4px}
.corr .why{font:var(--t-small);color:var(--ink-soft);max-width:66ch;margin:7px 0 0}


/* ------------------------------------------------------- the event record
   The side panel carries two kinds of record now. A component record is one
   part across many dates; an event record is one date across many parts. They
   share the panel, the header and the evidence grid, and differ only here. */
.ev-parts{display:flex;flex-direction:column;gap:2px;margin-top:8px}
.ev-part{display:grid;grid-template-columns:104px 1fr 18px;gap:10px;align-items:center;
  width:100%;text-align:left;padding:9px 10px;background:none;border:0;cursor:pointer;
  border-top:1px solid var(--rule)}
.ev-part:last-child{border-bottom:1px solid var(--rule)}
.ev-part:hover{background:var(--fill)}
.ev-part .id{font:var(--t-mono);color:var(--secondary);letter-spacing:.04em}
.ev-part .nm{font:var(--t-small)}
.ev-part .go{color:var(--secondary);text-align:right}
.evnav{display:flex;justify-content:space-between;gap:10px;margin:22px 0 6px;
  padding-top:14px;border-top:1px solid var(--rule)}
.evnav button{font:var(--t-mono);letter-spacing:.06em;color:var(--secondary);
  background:none;border:0;padding:6px 0;cursor:pointer}
.evnav button:hover{color:var(--ink)}
@media(max-width:760px){
  .ev-part{grid-template-columns:1fr 18px;gap:2px 10px}
  .ev-part .id{grid-column:1/2}
  .ev-part .nm{grid-column:1/2}
  .ev-part .go{grid-row:1/3;grid-column:2/3}
}


/* ------------------------------------------------------------- the facets
   Six axes, each a row of values with its own count. The counts are over the
   whole register rather than over the filtered view, because a count of what
   you are already looking at tells you nothing about the shape of the work. */
.lede2{font:var(--t-small);color:var(--ink-soft);max-width:62ch;margin:-6px 0 22px}
/* The facets are now a disclosure. Six axes and thirty-one values is a wall,
   and a wall is where a reader stops reading — but hiding a filter that is ON
   would be worse than the wall, so what is switched on comes out in front of
   it as chips and only the choosing is folded away. */
details.facets{display:block;margin:0 0 24px;padding:0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
details.facets > summary{
  list-style:none;cursor:pointer;padding:13px 0;display:flex;gap:12px;
  align-items:baseline;font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--ink);min-height:var(--tap)}
details.facets > summary::-webkit-details-marker{display:none}
details.facets > summary::after{
  content:'+';margin-left:auto;font:var(--t-body);color:var(--secondary);
  line-height:1;transform:translateY(1px)}
details.facets[open] > summary::after{content:'–'}
details.facets > summary:hover{color:var(--green)}
details.facets > summary .sub{font:var(--t-small);letter-spacing:0;
  text-transform:none;color:var(--secondary)}
details.facets > .facetrow:first-of-type{padding-top:2px}
details.facets > .facetrow{margin-bottom:7px}
details.facets > .facetrow:last-of-type{margin-bottom:18px}

/* Active filters, in front of the disclosure. A filtered list that does not
   say it is filtered is a list that lies about how many parts this car has. */
.fchips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 16px}
.fchip{display:inline-flex;align-items:baseline;gap:7px;padding:5px 9px;cursor:pointer;
  background:var(--ink);border:1px solid var(--ink);border-radius:2px;
  font:var(--t-small);color:#fff}
.fchip .ft{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:#fff;opacity:.62}
.fchip .x{font:var(--t-body);line-height:1;opacity:.7;transform:translateY(1px)}
.fchip:hover .x{opacity:1}
.fchip.clear{background:none;border-style:dashed;border-color:var(--rule);
  color:var(--secondary)}
.fchip.clear:hover{color:var(--ink);border-color:var(--secondary)}
.facetrow{display:grid;grid-template-columns:76px 1fr;gap:12px;align-items:baseline}
.facetrow .ft{font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--secondary)}
.facetrow .fc{display:flex;flex-wrap:wrap;gap:5px}
.facet{display:inline-flex;align-items:baseline;gap:6px;padding:4px 9px;cursor:pointer;
  background:none;border:1px solid var(--rule);border-radius:2px;
  font:var(--t-small);color:var(--ink-soft)}
.facet span{font:var(--t-mono);color:var(--secondary)}
.facet:hover{border-color:var(--secondary);color:var(--ink)}
.facet[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
.facet[aria-pressed="true"] span{color:#fff;opacity:.7}
.facet.clear{align-self:flex-start;margin-left:88px;border-style:dashed}
.asrec{font:var(--t-mono);color:var(--secondary);font-style:normal;display:block;margin-top:2px}
@media(max-width:760px){
  .facetrow{grid-template-columns:1fr;gap:4px}
  .facet.clear{margin-left:0}
}


/* ------------------------------------------------------------- diagnostic
   Only ever present with ?diag=1 — see wireDiag() in app.js. Deliberately
   plain: it exists to be photographed and read, not to look like part of the
   site. */
#diag{
  position:fixed;left:8px;top:8px;z-index:99;
  display:grid;grid-template-columns:auto 1fr;gap:1px 10px;
  max-width:calc(100% - 16px);padding:10px 12px;
  background:rgba(255,255,255,.94);border:1px solid var(--rule);
  font:11px/1.45 var(--mono);color:var(--ink);
}
#diag b{font-weight:400;color:var(--secondary);white-space:pre}
#diag button{margin-top:6px;padding:5px 10px;border:1px solid var(--green);
  background:var(--green);color:#fff;font:inherit;border-radius:999px}
#diag i{font-style:normal;color:var(--green)}
#diag span{word-break:break-all}


/* ---------------------------------------------------------- contact form
   Same field language as the admin panel's forms: a mono label above a plain
   box, and no decoration that would make this read as a marketing page. */
.cf{max-width:56ch;margin-top:26px;display:grid;gap:16px}
.cf label{display:block;font:var(--t-label);letter-spacing:var(--track-label);
  text-transform:uppercase;color:var(--secondary)}
.cf input,.cf textarea{
  display:block;width:100%;margin-top:6px;padding:11px 12px;
  border:1px solid var(--rule);background:var(--sheet);color:var(--ink);
  font:var(--t-small);line-height:1.5;border-radius:0;
}
.cf textarea{resize:vertical;min-height:120px}
.cf input:focus,.cf textarea:focus{outline:2px solid var(--green);outline-offset:-2px}
.cf input::placeholder{color:var(--secondary)}
/* The honeypot: off the screen rather than display:none, because some bots skip
   what is not rendered and a person never reaches it either way. */
.cf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.cf-act{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.cf-go{
  min-height:var(--tap);padding:0 22px;border:1px solid var(--green);
  background:var(--green);color:#fff;border-radius:999px;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;
}
.cf-go[disabled]{opacity:.55}
.cf-msg{font:var(--t-small);color:var(--secondary)}
.cf-msg[data-tone="ok"]{color:var(--green)}
.cf-msg[data-tone="bad"]{color:var(--a-replace)}
.cf-note{margin:0;font:var(--t-small);color:var(--ink-soft);line-height:1.65;max-width:60ch}

/* The menu's contact link sits with the footer rather than in the numbered
   groups: those are the record, and this is a way of reaching a person. */
#menu .foot .cx{display:block;color:var(--ink);text-decoration:none;
  font:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase}
#menu .foot .cx:hover{color:var(--green)}
