/* kit-draw.css: "The Roofcraft drawing board".
   The one visual vocabulary for every page (VISUAL-PLAN.md section 3). Paste the markup from
   src/partials/kit/*.html, link this file once, change nothing here.

   Owned by the kit. Page builders: do NOT edit. Ask for a piece instead.
   Reference: assets/KIT.md

   Rules this file keeps: hex only, no em-dash, no dash ornament, no tracked kicker, no gradient
   text, nothing you read under 14px, every drawing fully visible with no JS and with motion off.
   No JavaScript at all: the only motion is CSS scroll-driven, so there is no observer to deadlock
   and no script to fail. */

/* ------------------------------------------------------------------ the pen */
.dw {
  --dw-line: #363237;      /* main line */
  --dw-guide: #9a9295;     /* lead: hidden lines, hatching, leaders. never text */
  --dw-slate: #3d4042;     /* Welsh slate */
  --dw-slate-2: #4b4e52;   /* the next course along */
  --dw-oak: #735f3a;       /* timber, small doses */
  --dw-sky: #e8eef5;       /* sky, ground, masonry */
  --dw-void: #16181b;      /* a hole: a gap in the courses, a missing joint */
  --dw-paper: #ffffff;     /* a painted board: fascia, soffit */
  --dw-red: #ab2a1e;       /* the ridge, the chevron, the one thing being named */
  --dw-ground: #ffffff;    /* what the drawing sits on */
  --dw-rule: #dcd9da;      /* the sheet edge */
  --dw-chip-bg: #363237;   /* label chip: white Jost on Staffordshire Blue, 12.6:1 */
  --dw-chip-ink: #ffffff;
  --dw-ink: #16181b;
  --dw-muted: #4d4f54;     /* 8.2:1 on white */
  --dw-link: #ab2a1e;      /* 6.4:1 on white */
  --dw-sans: var(--sans, "Jost", Arial, Helvetica, sans-serif);
  --dw-serif: var(--serif, "Brygada", Georgia, serif);
}
/* on Staffordshire Blue. Put .dw--on-dark on the piece, or .on-dark on the band. */
.dw--on-dark :focus-visible { outline-color: #f08a7c; }
.dw--on-dark,
.on-dark .dw {
  --dw-line: #c6c4cb;
  --dw-guide: #a39ca0;
  --dw-slate: #4a4e53;
  --dw-slate-2: #3b3f44;
  --dw-oak: #5b4a2e;
  --dw-sky: #3a363c;
  --dw-void: #101114;
  --dw-red: #f08a7c;
  --dw-ground: #2f2b30;
  --dw-rule: #4d484f;
  --dw-chip-bg: #ffffff;
  --dw-chip-ink: #16181b;
  --dw-ink: #ffffff;
  --dw-muted: #c6c4cb;     /* 7.3:1 on #363237 */
  --dw-link: #ffffff;      /* the red is 1.7:1 on a dark card, so links go white, as .busy a does */
}

/* every drawing reserves its own height from its viewBox, so nothing shifts */
.dw svg { display: block; width: 100%; height: auto; }

/* the strokes and fills. Classes, not var() in presentation attributes, so the on-dark
   inversion is one cascade away and old engines never see an unparsed attribute. */
.dw .d-ln { fill: none; stroke: var(--dw-line); stroke-width: 1.8; stroke-linejoin: miter; }
.dw .d-ed { fill: none; stroke: var(--dw-guide); stroke-width: 1; }
.dw .d-gd { fill: none; stroke: var(--dw-guide); stroke-width: 1; stroke-dasharray: 4 3; }
.dw .d-hx { fill: none; stroke: var(--dw-guide); stroke-width: .8; }
.dw .d-sl { fill: var(--dw-slate); stroke: var(--dw-guide); stroke-width: 1; }
.dw .d-s2 { fill: var(--dw-slate-2); stroke: var(--dw-guide); stroke-width: 1; }
.dw .d-ok { fill: var(--dw-oak); stroke: var(--dw-line); stroke-width: 1; }
.dw .d-sk { fill: var(--dw-sky); stroke: var(--dw-line); stroke-width: 1; }
.dw .d-pp { fill: var(--dw-paper); stroke: var(--dw-line); stroke-width: 1.2; }
.dw .d-mu { fill: var(--dw-guide); stroke: none; }
.dw .d-wt { fill: var(--dw-sky); stroke: var(--dw-line); stroke-width: 1; }
.dw .d-rd { fill: none; stroke: var(--dw-red); stroke-width: 2.2; stroke-linejoin: miter; }
.dw .d-rh { fill: none; stroke: var(--dw-red); stroke-width: 3.6; stroke-linejoin: miter; }
.dw .d-rf { fill: var(--dw-red); stroke: none; }
.dw .d-vd { fill: var(--dw-void); stroke: none; }
.dw .d-fr { fill: var(--dw-ground); stroke: var(--dw-line); stroke-width: 1.8; stroke-linejoin: miter; }
.dw .d-ldr { fill: none; stroke: var(--dw-guide); stroke-width: 1; }
.dw .d-dot { fill: var(--dw-red); stroke: none; }

/* the sheet a drawing sits on */
.dw .d-sheet {
  background: var(--dw-ground);
  border: 1px solid var(--dw-rule);
  border-radius: 3px;
}

/* ------------------------------------------------------- 1. dw-callout */
/* One drawn object, 3 to 5 leader-line labels of 1 to 3 words. Replaces a bullet list of parts. */
/* The chip hangs off the END of its leader, never off the frame edge: set --x to the leader's
   start x divided by the viewBox width (and --y to its start y / viewBox height), then
   data-anchor="end" when the leader runs right, none when it runs left. The pair then stays
   joined at every width, which a percentage against the frame does not.
   The callout needs at least 340px of column to read. */
.dw-callout { margin: 0; max-width: var(--dw-max, 640px); }
.dw-callout__frame { position: relative; }
.dw-callout__labels { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }
.dw-label {
  position: absolute;
  left: var(--x); top: var(--y);
  transform: translateY(-50%);
  margin: 0;
  padding: 5px 9px;
  background: var(--dw-chip-bg);
  color: var(--dw-chip-ink);
  font: 600 .875rem/1.2 var(--dw-sans);
  border-radius: 3px;
  white-space: nowrap;
}
.dw-label { transform: translate(5px, -50%); }
.dw-label[data-anchor="end"] { transform: translate(calc(-100% - 5px), -50%); }
.dw-label[data-anchor="mid"] { transform: translate(-50%, -50%); }
.dw-callout__cap {
  margin: 10px 0 0;
  font: 400 .9375rem/1.45 var(--dw-sans);
  color: var(--dw-muted);
}

/* ------------------------------------------------------- 2. dw-symptom */
/* A row of one-fault drawings with a 2-to-4 word name under each.
   Replaces "what you might be seeing" bullet prose. */
.dw-symptoms {
  max-width: var(--dw-max, 1020px);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px 10px;
  margin: 0; padding: 0; list-style: none;
}
@media (min-width: 768px) {
  .dw-symptoms { grid-template-columns: repeat(var(--cols, 5), 1fr); gap: 22px 16px; }
}
.dw-symptom { margin: 0; text-align: center; }
.dw-symptom__art { width: 100%; }
.dw-symptom__name {
  margin: 8px 0 0;
  font: 600 .9375rem/1.25 var(--dw-sans);
  color: var(--dw-ink);
  text-wrap: balance;
}

/* ------------------------------------------------------- 3. dw-steps */
/* 3 or 4 drawings in order, one verb each plus 12 words max. The order is the explanation.
   Replaces a "what happens next" paragraph. */
.dw-steps { max-width: var(--dw-max, 1020px); display: grid; gap: 20px; margin: 0; padding: 0; list-style: none; }
@media (min-width: 768px) { .dw-steps { grid-template-columns: repeat(var(--cols, 3), 1fr); gap: 28px; } }
.dw-step { margin: 0; }
.dw-step__art { width: 100%; }
.dw-step__head { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.dw-step__n {
  flex: none;
  display: grid; place-items: center;
  width: 26px; height: 26px;
  border: 2px solid var(--dw-red);
  border-radius: 3px;
  font: 600 .9375rem/1 var(--dw-sans);
  color: var(--dw-red);
}
.dw-step__verb { margin: 0; font: 600 1.0625rem/1.2 var(--dw-sans); color: var(--dw-ink); }
.dw-step__line { margin: 6px 0 0; font: 400 .9375rem/1.45 var(--dw-sans); color: var(--dw-muted); }

/* ------------------------------------------------------- 4. dw-compare */
/* The same object drawn twice, the one difference picked out in red.
   Replaces a "what is the difference" paragraph. */
.dw-compare { max-width: var(--dw-max, 760px); display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 0; }
@media (min-width: 768px) { .dw-compare { gap: 28px; } }
.dw-compare__panel { margin: 0; }
.dw-compare__art { width: 100%; }
.dw-compare__name {
  margin: 10px 0 0;
  font: 600 1.25rem/1.15 var(--dw-serif);
  color: var(--dw-ink);
}
.dw-compare__key { margin: 3px 0 0; font: 600 .9375rem/1.3 var(--dw-sans); color: var(--dw-red); }
.dw-compare__line { margin: 5px 0 0; font: 400 .9375rem/1.45 var(--dw-sans); color: var(--dw-muted); }

/* ------------------------------------------------------- 5. dw-tradecard */
/* Their 2015 letterhead re-drawn. The facts stay facts, on a card instead of in four paragraphs. */
.dw-tradecard {
  margin: 0;
  padding: 16px;
  background: var(--dw-ground);
  border: 1px solid var(--dw-rule);
  border-radius: 4px;
}
@media (min-width: 768px) { .dw-tradecard { padding: 24px; } }
.dw-tradecard__head { width: 100%; max-width: 320px; }
.dw-tradecard__name {
  margin: 12px 0 0;
  font: 600 1.25rem/1.15 var(--dw-serif);
  color: var(--dw-ink);
}
.dw-tradecard__facts { margin: 12px 0 0; max-width: 560px; display: grid; gap: 10px; }
@media (min-width: 560px) {
  .dw-tradecard__facts { grid-template-columns: max-content 1fr; gap: 10px 18px; align-items: baseline; }
}
.dw-tradecard__facts dt {
  margin: 0;
  font: 600 .875rem/1.3 var(--dw-sans);
  color: var(--dw-muted);
}
.dw-tradecard__facts dd {
  margin: 0;
  font: 400 1rem/1.4 var(--dw-sans);
  color: var(--dw-ink);
}
.dw-tradecard__marks {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin: 16px 0 0; padding: 14px 0 0;
  border-top: 1px solid var(--dw-rule);
  list-style: none;
}
.dw-tradecard a { color: var(--dw-link); }
.dw-tradecard__marks li { margin: 0; }
.dw-tradecard__marks img { width: 72px; height: auto; }
.dw-tradecard__marks .dw-tradecard__tile {
  display: block; padding: 6px; background: #ffffff; border-radius: 3px;
}

/* ------------------------------------------------------- 6. dw-reach */
/* Annscroft at the apex and the places their own posts name. No distances, no times, no radius. */
.dw-reach { margin: 0; max-width: var(--dw-max, 680px); }
.dw-reach__art { width: 100%; }
.dw-reach__places {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
  margin: 12px 0 0; padding: 0; list-style: none;
}
.dw-reach__places li {
  margin: 0; padding: 7px 12px;
  border: 1px solid var(--dw-rule);
  border-radius: 3px;
  font: 600 .9375rem/1.2 var(--dw-sans);
  color: var(--dw-ink);
}
.dw-reach__places li[data-base] {
  border-color: var(--dw-red);
  color: var(--dw-red);
}

/* ------------------------------------------------------- 7. dw-figure */
/* One fact set large inside a drawn frame. A number is a picture (Dyson R6).
   The frame wraps the NUMBER only; the caption sits under it, so a long value never crowds. */
.dw-figure { margin: 0; display: inline-grid; justify-items: center; }
.dw-figure__box {
  position: relative;
  display: grid; place-items: center;
  min-width: 168px; min-height: 120px;
  padding: 16px 24px;
}
/* .dw svg sets height:auto, which would let the frame grow past the box and cover the caption */
.dw .dw-figure__frame { position: absolute; inset: 0; width: 100%; height: 100%; }
/* the frame stretches to whatever the fact needs, so the strokes must not stretch with it */
.dw-figure__frame * { vector-effect: non-scaling-stroke; }
.dw-figure__n {
  position: relative;
  font-family: var(--dw-serif);
  font-weight: 600;
  font-size: var(--dw-fig-size, clamp(3.5rem, 2.9rem + 2.6vw, 4.5rem));
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--dw-ink);
}
.dw-figure__cap {
  margin: 10px 0 0;
  max-width: 20ch;
  text-align: center;
  font: 400 .9375rem/1.35 var(--dw-sans);
  color: var(--dw-muted);
}
.dw-figures { display: flex; flex-wrap: wrap; align-items: start; gap: 20px 16px; margin: 0; padding: 0; list-style: none; }
.dw-figures > li { margin: 0; }

/* ------------------------------------------------------------------ motion */
/* Three pieces move, and only where the movement is doing explanatory work:
     dw-callout  the labels name the parts one at a time
     dw-steps    the order IS the explanation
     dw-compare  the one difference arrives last, so you see what changed
   dw-symptom, dw-figure, dw-tradecard and dw-reach are static on purpose.

   Everything above is already the FINISHED state, so the reduced-motion still, the no-JS state
   and the no-scroll-timeline state are all complete with nothing to undo. Scroll-driven only:
   no IntersectionObserver, so none of the clip-path/observer deadlocks in
   reference_reveal_visibility_traps can happen here.

   Ranges are "cover" not "entry": html{scroll-padding-top} insets an entry timeline, and at 390
   the sticky call bar covers the bottom 70px, so nothing starts down there. Easing is linear on
   every segment, because an ease across a scroll range front-loads into a pop.

   The from-state opacity is .001, never 0: _work/text_density.py skips any element at computed
   opacity 0, so a true 0 would quietly stop counting the words inside it and flatter the page. */
@keyframes dw-draw { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes dw-pop  { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: none; } }
@keyframes dw-chip { from { opacity: .001; transform: translateY(-50%) translateX(-7px); }
                     to   { opacity: 1;    transform: translateY(-50%); } }
@keyframes dw-chip-end { from { opacity: .001; transform: translate(-100%, -50%) translateX(7px); }
                         to   { opacity: 1;    transform: translate(-100%, -50%); } }
@keyframes dw-chip-mid { from { opacity: .001; transform: translate(-50%, -50%) scale(.94); }
                         to   { opacity: 1;    transform: translate(-50%, -50%); } }
@keyframes dw-rise { from { opacity: .001; transform: translateY(10px); }
                     to   { opacity: 1;    transform: none; } }
@keyframes dw-fade { from { opacity: .001; } to { opacity: 1; } }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    .dw-callout__frame { view-timeline-name: --dw-callout; }
    .dw-callout .d-ldr,
    .dw-callout .d-dot,
    .dw-callout .dw-label {
      animation-timeline: --dw-callout;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-duration: 1ms; /* ignored on a scroll timeline, kept for engines that want one */
      animation-range: cover calc(20% + var(--i, 0) * 8%) cover calc(34% + var(--i, 0) * 8%);
    }
    .dw-callout .d-ldr { stroke-dasharray: 100; animation-name: dw-draw; }
    .dw-callout .d-dot { animation-name: dw-pop; transform-box: fill-box; transform-origin: 50% 50%; }
    .dw-callout .dw-label { animation-name: dw-chip; }
    .dw-callout .dw-label[data-anchor="end"] { animation-name: dw-chip-end; }
    .dw-callout .dw-label[data-anchor="mid"] { animation-name: dw-chip-mid; }

    .dw-steps { view-timeline-name: --dw-steps; }
    .dw-steps .dw-step {
      animation: dw-rise linear both;
      animation-timeline: --dw-steps;
      animation-range: cover calc(16% + var(--i, 0) * 9%) cover calc(30% + var(--i, 0) * 9%);
    }

    .dw-compare { view-timeline-name: --dw-compare; }
    .dw-compare .d-rd,
    .dw-compare .d-rh,
    .dw-compare .d-rf,
    .dw-compare .d-diff {
      animation: dw-fade linear both;
      animation-timeline: --dw-compare;
      animation-range: cover calc(34% + var(--i, 0) * 7%) cover calc(48% + var(--i, 0) * 7%);
    }
  }
}
