/* ============================================================================
   vespa-dossier — the tab and the drawer.

   THE SIGNATURE MOVE, and the thing vespa-archive's registry row admits it
   never had.

   The world is an archive shot from above: folders on a worktop, and the only
   colour in the entire film is the mint on their tabs. So the button is a tab.
   It hangs off the bottom edge of the plate the way a tab hangs off a folder
   lying flat, it carries the real section title and a measured word count, and
   pulling it brings the drawer with it. The tab does not disappear and get
   replaced by a panel: it travels to the screen edge and lands as the drawer's
   own spine, same colour, same words, so nothing on this page appears from
   nowhere.

   Mint is #61D790 and it is the print system's green. It fails contrast as TYPE
   on paper, which is why the interface accent elsewhere is the darker #2E7D4F.
   As a GROUND under ink it measures 7.5:1, so the tab is the one place the real
   brand green can be used at full strength and still be read. That is not a
   workaround, it is where print already puts it.

   EVERYTHING HERE IS GATED BEHIND .js, deliberately.

   The five sections are real markup in the document at all times, because an AI
   crawler does not run JavaScript and this page exists to carry the document.
   With JS off, none of the rules below apply and the drawers are an ordinary
   appendix: five articles, in order, that read top to bottom.
   ========================================================================= */

/* ==================================================================== TAB ==
   Present in both modes. With JS off it is still a link that jumps to its
   section, so it never becomes a dead control.
*/
.tab{
  --tab-face:var(--mint);
  position:relative;
  display:inline-flex;align-items:center;gap:.85rem;
  align-self:flex-start;
  min-height:var(--tab-h);
  padding:.6rem 1rem .68rem 1.15rem;
  background:var(--tab-face);
  color:var(--ink);
  text-decoration:none;
  /* The print system's chamfer, on the leading top corner. A file tab is not a
     rectangle, and this is the same 10px cut the book uses on every plate. */
  clip-path:polygon(0 0, calc(100% - 11px) 0, 100% 11px, 100% 100%, 0 100%);
  box-shadow:0 1px 2px rgba(46,47,39,.14), 0 10px 20px -16px rgba(46,47,39,.5);
  transition:transform .38s cubic-bezier(.22,1,.36,1),
             background-color .3s ease, box-shadow .38s ease;
}

/* The overhang. The tab drops past the plate's bottom edge by its own padding
   plus a little, which is what makes it read as attached to the sheet rather
   than sitting on it.

   ONLY as the last child. A negative bottom margin pulls whatever follows up
   underneath the tab, and on the close plate that put the tab directly on top
   of the CTA. The template now orders the tab last everywhere; this selector is
   the guard that makes a future reorder fail visibly rather than by collision. */
.blk > .tab:last-child{
  margin-bottom:calc(-1 * var(--plate-pad) - .55rem);
}
.blk > .tab{margin-top:.25rem}
.blk--trail > .tab{align-self:flex-start}
@media (min-width:52rem){
  /* Trail plates are right-anchored, so their tab hangs from the right edge,
     mirroring the sheet it belongs to. */
  .blk--trail > .tab{
    align-self:flex-end;
    clip-path:polygon(11px 0, 100% 0, 100% 100%, 0 100%, 0 11px);
    padding:.55rem 1.15rem .55rem 1rem;
  }
}

/* The grip. Three ridges, the moulded detail on the end of a real drawer pull.
   Decorative, aria-hidden, and the only ornament on the page. */
.tab__grip{
  flex:none;width:.5rem;height:1.15rem;
  background:repeating-linear-gradient(to right,
    rgba(46,47,39,.34) 0 1px, transparent 1px 3px);
}
.tab__in{display:flex;flex-direction:column;gap:.1rem;min-width:0}
.tab__t{
  font-family:var(--sc-font-display);font-weight:500;
  font-size:.9rem;line-height:1.2;letter-spacing:-.008em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:17rem;
}
.tab__m{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.11em;
  text-transform:uppercase;color:rgba(46,47,39,.62);
}
.tab__vis{flex:none;display:flex;transition:transform .38s cubic-bezier(.22,1,.36,1)}
.tab__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

.tab:hover,.tab:focus-visible{
  background:#7FE0A6;
  transform:translateY(5px);
  box-shadow:0 2px 3px rgba(46,47,39,.16), 0 16px 26px -18px rgba(46,47,39,.55);
}
.tab:hover .tab__vis,.tab:focus-visible .tab__vis{transform:translateX(4px)}
.tab:active{transform:translateY(2px)}

/* The idle breathe. Two pixels, six seconds, and it exists because a tab that
   never moves is a rectangle.

   IT ONLY RUNS WHEN THE PAGE IS STILL, and that is a performance fix as much as
   a taste one. The tab carries a clip-path and a box-shadow and it lives inside
   a copy block the engine re-transforms every scroll frame, so an always-on
   transform animation on five of them was main-thread paint work competing with
   the scrub for the same frame. `data-idle` is set by dossier.js 400ms after
   scrolling stops.

   It also reads better this way. The tab is still while you are moving through
   the film and starts inviting the moment you stop, which is when the offer is
   actually relevant. */
@media (prefers-reduced-motion:no-preference){
  /* No space. data-idle is set on <html>, which is also the .js element, so
     `.js [data-idle]` looked for a DESCENDANT carrying it and matched nothing:
     the tabs never breathed at all. */
  .js[data-idle] .tab{animation:tab-breathe 6s ease-in-out infinite}
  .js .tab:hover,.js .tab:focus-visible,.js .tab[data-pulled]{animation:none}
}
@keyframes tab-breathe{
  0%,100%{transform:translateY(0)}
  50%    {transform:translateY(2px)}
}

/* Pulled. The tab leaves toward the edge its own drawer arrives from, so the
   two motions are still one motion now that the sides differ per leg. */
.js .tab[data-pulled]{
  opacity:0;
  transition:transform .42s cubic-bezier(.55,0,.85,.35), opacity .3s ease .06s;
}
.js .tab[data-pull="right"][data-pulled]{transform:translateX(2.5rem)}
.js .tab[data-pull="left"][data-pulled]{transform:translateX(-2.5rem)}
@media (max-width:52rem){
  /* One sheet, rising from the bottom, so every tab travels down. */
  .js .tab[data-pull][data-pulled]{transform:translateY(2.5rem)}
}

/* ================================================================== LOCK ==
   Set by dossier.js while a drawer is open. See the note there: the body must
   NOT leave the flow, because the worldflight's scroll track is the document's
   height and a fixed body has none. Losing it snapped the world to leg 1.
   --sbw is the width the vanished scrollbar gave back. */
.js.is-locked{overflow:hidden}
.js.is-locked body{overflow:hidden}
.js.is-locked .bar__in{padding-right:calc(var(--pad) + var(--sbw,0px))}

/* ================================================================== VEIL == */
.veil{display:none}
.js .veil{
  display:block;position:fixed;inset:0;z-index:70;
  background:rgba(46,47,39,.34);
  backdrop-filter:blur(2px);
  opacity:0;pointer-events:none;
  transition:opacity .45s ease;
}
.js .veil[data-on]{opacity:1;pointer-events:auto}

/* ================================================================ DRAWER ==
   With JS off everything below is inert and .dossier is an appendix.
*/
/* 48rem, not the page's 80rem. With JS off this is a document to be read, not a
   layout, and an 80rem container leaves a 34rem measure floating against a
   half-empty right side. */
.dossier{
  max-width:48rem;margin-inline:auto;padding:4rem var(--pad) 6rem;
}
.dossier__h{
  font-family:var(--sc-font-display);font-weight:500;
  font-size:clamp(1.5rem,1.1rem+1.4vw,2.2rem);margin:0 0 2.5rem;
}
/* With JS the appendix has no layout of its own: every drawer is fixed, so the
   section collapses to nothing and the page still ends on the film's last
   frame, exactly as vespa-archive does. */
.js .dossier{max-width:none;margin:0;padding:0}
.js .dossier__h{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0}

.dr{margin:0 0 4rem;max-width:44rem}

.js .dr{
  position:fixed;z-index:80;
  width:var(--drawer-w);max-width:none;margin:0;
  display:flex;
  visibility:hidden;
  transition:transform .56s cubic-bezier(.22,1,.36,1), visibility 0s linear .56s;

  /* A closed drawer is still five hundred nodes of prose and a hundred-node
     SVG, and the browser was laying all of it out on every reflow: full-document
     layout measured 3.7ms with the drawers live against 1.7ms without. The
     engine forces several layouts per scroll frame, so that was being paid over
     and over for content nobody is looking at. content-visibility skips the
     subtree entirely while leaving the element itself in the flow, so the slide
     transition still runs on the element's own transform, and the markup stays
     in the HTML for crawlers, which is the whole point of the build. */
  content-visibility:hidden;
  contain-intrinsic-size:auto 100vh;
}
/* Warmed one frame before opening. A closed drawer's subtree is not laid out at
   all, so flipping content-visibility and the transform in the same frame made
   the browser lay out five hundred nodes before it could start the slide, and
   the slide began late and stuttered. dossier.js sets data-warm, yields a frame,
   then sets data-open. */
.js .dr[data-warm]{content-visibility:visible}
.js .dr[data-open]{
  visibility:visible;
  content-visibility:visible;
  transition:transform .56s cubic-bezier(.22,1,.36,1), visibility 0s;
}

/* The side is decided per leg and mirrors the plate. See copy.py. */
.js .dr[data-side="right"]{
  inset:0 0 0 auto;transform:translateX(100%);
  box-shadow:-24px 0 60px -40px rgba(46,47,39,.65);
}
.js .dr[data-side="left"]{
  inset:0 auto 0 0;transform:translateX(-100%);
  box-shadow:24px 0 60px -40px rgba(46,47,39,.65);
  /* Spine on the inner edge, so it always faces the page rather than the
     window edge. Same object, mirrored, not a second treatment. */
  flex-direction:row-reverse;
}
.js .dr[data-side="left"] .dr__spine{
  border-right:0;border-left:1px solid rgba(46,47,39,.18);
}

/* The open transform has to be MORE specific than the two side rules, not just
   earlier. `.js .dr[data-open]` and `.js .dr[data-side="left"]` weigh exactly
   the same, so the side rule won on document order and every left drawer stayed
   parked off-screen with data-open set and nothing visible. */
.js .dr[data-side][data-open]{transform:none}

/* THE SPINE. Where the tab lands. Same mint, same title, rotated. */
.dr__spine{display:none}
.js .dr__spine{
  display:flex;align-items:center;justify-content:flex-end;
  flex:none;width:var(--spine-w);
  background:var(--mint);
  border-right:1px solid rgba(46,47,39,.18);
}
.js .dr__spine span{
  writing-mode:vertical-rl;transform:rotate(180deg);
  font-family:var(--sc-font-display);font-weight:500;font-size:.8rem;
  letter-spacing:.02em;color:var(--ink);
  padding-block:1.4rem;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

.dr__panel{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.js .dr__panel{background:var(--sc-surface);overflow:hidden}

/* -------------------------------------------------------------------- head */
.dr__head{
  display:grid;grid-template-columns:1fr auto;align-items:start;
  gap:.6rem 1rem;
  /* In the appendix nothing separates the head from the prose, so the deck
     collides with the title. The panel gets the same separation from its
     border instead. */
  margin-bottom:1.6rem;
}
.js .dr__head{
  margin-bottom:0;
  flex:none;
  padding:clamp(1.4rem,3vw,2.25rem) clamp(1.4rem,3vw,2.5rem) 1.15rem;
  border-bottom:1px solid var(--hair);
}
.dr__way{
  grid-column:1;margin:0;
  font-family:var(--mono);font-size:.64rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--sc-accent);
}
.dr__head .rule{grid-column:1;margin:.55rem 0 0}
.dr__title{
  grid-column:1;margin:.55rem 0 0;
  font-family:var(--sc-font-display);font-weight:500;
  font-size:clamp(1.3rem,1rem+1.1vw,1.95rem);line-height:1.14;
  letter-spacing:-.02em;text-wrap:balance;
}
.dr__x{display:none}
.js .dr__x{
  grid-column:2;grid-row:1 / span 3;align-self:start;
  display:inline-flex;align-items:center;gap:.5rem;
  background:none;border:1px solid var(--hair);color:rgba(46,47,39,.7);
  font-family:var(--mono);font-size:.63rem;letter-spacing:.13em;
  text-transform:uppercase;cursor:pointer;
  padding:.5rem .7rem;
  transition:border-color .25s ease,color .25s ease,background-color .25s ease;
}
.js .dr__x:hover{border-color:var(--ink);color:var(--ink);background:rgba(46,47,39,.04)}

/* -------------------------------------------------------------------- body */
.js .dr__body{
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:clamp(1.5rem,3vw,2.25rem) clamp(1.4rem,3vw,2.5rem) 2rem;
  scrollbar-gutter:stable;
  /* A short fade at the bottom edge. Without it the panel cuts a line of type
     in half against the nav, which reads as a rendering fault rather than as
     more text below. 1.75rem, so it never hides a whole line. */
  mask-image:linear-gradient(to bottom, #000 calc(100% - 1.75rem), transparent);
}
.dr__body > * + *{margin-top:1.05rem}
.dr__body p{
  margin:0;font-size:clamp(.95rem,.92rem+.15vw,1.02rem);line-height:1.66;
  color:rgba(46,47,39,.78);
  /* 34rem, not 38. At 38 the panel's own width was the limit rather than this
     rule, and lines ran to about 78 characters. Prose wants 60 to 70. */
  max-width:34rem;
}
.dr__body strong{font-weight:600;color:var(--ink)}
.dr__deck{
  font-family:var(--sc-font-display);
  font-size:clamp(1.2rem,1.05rem+.7vw,1.55rem)!important;
  line-height:1.32!important;color:var(--ink)!important;font-weight:500;
  letter-spacing:-.016em;text-wrap:balance;max-width:30rem!important;
}
/* The deck is the section's own standfirst, so what follows it starts a new
   thought and needs more than the standard rhythm. */
.dr__deck + p{margin-top:1.7rem}
.dr__h{
  margin:2.5rem 0 0;
  font-family:var(--sc-font-display);font-weight:500;
  font-size:clamp(1.1rem,1rem+.5vw,1.35rem);letter-spacing:-.015em;
  padding-top:1.5rem;border-top:1px solid var(--hair);
}
/* The pulled sentence. The print book sets these against a green rule and so
   does the reading edition, so the third edition of the same document does not
   invent a fourth treatment for it. */
.dr__kick{
  margin-top:1.6rem!important;
  padding-left:1.1rem;border-left:3px solid var(--mint);
}
.dr__kick span{
  font-family:var(--sc-font-display);font-weight:500;
  font-size:clamp(1rem,.95rem+.35vw,1.15rem);line-height:1.45;
  color:var(--ink);
}

/* The eight techniques. A tile grid, which is how print sets them, rather than
   eight bullets in a column. */
.caps{
  list-style:none;margin:1.4rem 0 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(13.5rem,1fr));gap:1px;
  background:var(--hair);border:1px solid var(--hair);
}
.cap{
  display:flex;align-items:flex-start;gap:.65rem;
  background:var(--sc-surface);padding:.85rem .9rem;
  font-size:.84rem;line-height:1.35;color:rgba(46,47,39,.82);
}
.cap__ic{flex:none;color:var(--sc-accent);margin-top:.05rem}

/* A numbered pillar. Four of them across two drawers. */
.pil{margin-top:2.5rem;padding-top:1.6rem;border-top:1px solid var(--hair)}
.pil__num{
  margin:0 0 .35rem!important;
  font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;
  color:var(--sc-accent)!important;
}
.pil__t{
  margin:0;font-family:var(--sc-font-display);font-weight:500;
  font-size:clamp(1.15rem,1rem+.6vw,1.45rem);letter-spacing:-.018em;
}
.pil__deck{
  margin:.4rem 0 1rem!important;
  font-family:var(--sc-font-display);font-size:1rem!important;
  color:var(--ink)!important;
}
.pil > p + p{margin-top:1.05rem}

/* The figure. The one real diagram in the source document, brought across from
   the reading edition unchanged. Its tokens are mapped here rather than in the
   file, so the same SVG serves both editions. */
.fig{
  margin:2rem 0 0;padding:1.5rem;
  background:var(--paper);border:1px solid var(--hair);
  --paper:#FFFFFF;
  --mist:#F1F0EA;
  --sage:#EAF5EE;
  --green:var(--mint);
  --green-12:rgba(97,215,144,.14);
  --ink-72:rgba(46,47,39,.72);
  --ink-54:rgba(46,47,39,.54);
  --ink-38:rgba(46,47,39,.38);
  --sans-display:var(--sc-font-display);
}
.fig svg{display:block;width:100%;height:auto}
.fig figcaption{
  margin-top:1rem;font-family:var(--mono);font-size:.63rem;letter-spacing:.13em;
  text-transform:uppercase;color:rgba(46,47,39,.55);
}

/* The three customers. Real logos, real sentences, and the four figures under
   them are quoted from those sentences. They do not count up: a counter spends
   a second showing numbers that are not true, and these are citations. */
.cases{list-style:none;margin:1.5rem 0 0;padding:0;display:grid;gap:1px;background:var(--hair);border:1px solid var(--hair)}
.case{background:var(--sc-surface);padding:1.15rem 1.15rem 1.3rem}
.case__logo{display:block;width:auto;max-width:9rem;height:26px;object-fit:contain;object-position:left center;margin-bottom:.8rem}
.case__claim{font-family:var(--sc-font-display);font-size:1rem!important;color:var(--ink)!important;margin:0 0 .5rem!important}
.case__body{font-size:.88rem!important;line-height:1.6!important}

.stats{
  margin-top:1.5rem;display:grid;grid-template-columns:1fr 1fr;gap:1px;
  background:var(--hair);border:1px solid var(--hair);
}
.stat{background:var(--sc-surface);padding:1rem 1rem 1.1rem}
.stat__over{margin:0 0 .1rem!important;font-family:var(--mono);font-size:.6rem!important;letter-spacing:.1em;text-transform:uppercase;color:rgba(46,47,39,.5)!important}
.stat__v{margin:0!important;font-family:var(--sc-font-display);font-weight:500;font-size:clamp(1.35rem,1.1rem+.9vw,1.9rem)!important;line-height:1.05!important;letter-spacing:-.02em;color:var(--ink)!important}
.stat__l{margin:.3rem 0 0!important;font-size:.76rem!important;line-height:1.35!important;color:rgba(46,47,39,.62)!important}

.socials{list-style:none;margin:1.1rem 0 0;padding:0;display:flex;flex-wrap:wrap;gap:.5rem}
.socials a{
  display:inline-block;padding:.42rem .8rem;border:1px solid var(--hair);
  font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--sc-accent);text-decoration:none;transition:border-color .25s ease;
}
.socials a:hover{border-color:var(--sc-accent)}

/* --------------------------------------------------------------------- nav
   Prev and next between drawers, so the five read as one document without ever
   closing back to the film. */
.dr__nav{
  display:flex;flex-wrap:wrap;gap:1px;background:var(--hair);
  border-top:1px solid var(--hair);
  margin-top:2.5rem;
}
.js .dr__nav{flex:none;margin-top:0;border-top:1px solid var(--hair)}
.dr__go{
  flex:1 1 12rem;min-width:0;
  display:flex;flex-direction:column;gap:.2rem;
  background:var(--sc-surface);
  padding:.9rem clamp(1.4rem,3vw,2.5rem);
  text-decoration:none;color:var(--ink);
  transition:background-color .25s ease;
}
.dr__go:hover{background:#F2F1EC}
.dr__go-l{font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;color:rgba(46,47,39,.5)}
.dr__go-t{font-family:var(--sc-font-display);font-weight:500;font-size:.9rem;line-height:1.25;overflow:hidden;text-overflow:ellipsis}
/* Direction, marked on the label rather than with an icon. Two glyphs and no
   extra markup, and it means "Back" and "Next" are not the only thing telling
   the reader which way the document runs. */
.dr__go--prev .dr__go-l::before{content:"\2190\00a0"}
.dr__go--next .dr__go-l::after{content:"\00a0\2192"}
.dr__go--next{text-align:right;align-items:flex-end}
.dr__go--cta{background:var(--sc-accent);color:var(--sc-accent-ink);justify-content:center}
.dr__go--cta:hover{background:#24663f}
.dr__go--cta .dr__go-t{font-size:1rem}
.dr__go--doc .dr__go-t{color:var(--sc-accent)}

/* ================================================================= MOBILE ==
   A bottom sheet, because a 46rem side panel on a 390px screen is a full
   takeover pretending to be a drawer. The tab travels down instead of right,
   the spine becomes the grab handle across the top, and the geometry still
   reads as one object arriving.
*/
@media (max-width:52rem){
  .js .dr,.js .dr[data-side="left"],.js .dr[data-side="right"]{
    inset:auto 0 0 0;width:auto;height:min(92svh,100%);
    flex-direction:column;
    transform:translateY(100%);
    box-shadow:0 -20px 50px -34px rgba(46,47,39,.7);
  }
  .js .dr[data-side][data-open]{transform:none}
  .js .dr__spine,.js .dr[data-side="left"] .dr__spine{
    width:auto;height:2.35rem;
    justify-content:center;align-items:center;
    border-right:0;border-left:0;border-bottom:1px solid rgba(46,47,39,.18);
  }
  .js .dr__spine span{
    writing-mode:horizontal-tb;transform:none;padding:0 1rem;font-size:.78rem;
  }
  .stats{grid-template-columns:1fr 1fr}
  .caps{grid-template-columns:1fr}
  .dr__go{flex:1 1 100%}
  .dr__go--next{text-align:left;align-items:flex-start}
}

/* ======================================================== REDUCED MOTION ==
   The drawer still arrives, it just does not travel. Removing the transition
   entirely would make the panel appear with no relationship to the tab that
   was clicked, which is worse for the people this setting exists for.
*/
@media (prefers-reduced-motion:reduce){
  .js .dr,.js .tab,.js .tab[data-pulled],.tab__vis{transition-duration:.01ms}
  .js .veil{transition-duration:.01ms}
}

/* ==================================================================== PRINT
   The film cannot print. The document can, and it is all here. */
@media print{
  .bar,.veil,.skip,[data-sc-progress],[data-sc-mode],.tab{display:none!important}
  .js .dossier{max-width:none;padding:0}
  .js .dossier__h{position:static;width:auto;height:auto;clip-path:none;margin:0 0 2rem}
  .js .dr{position:static;transform:none;visibility:visible;width:auto;display:block;box-shadow:none;page-break-after:always}
  .js .dr__spine,.js .dr__x,.dr__nav{display:none!important}
  .js .dr__body{overflow:visible;padding:0}
  main{padding-top:0}
}
