/* Brand My Framework — built on Framework's own design language.
   Palette, radii and type scale are read from frame.work's shipped CSS.

   Type: Graphik (Commercial Type) over DM Mono is Framework's pairing.
   DM Mono ships here for real, from Google Fonts. Graphik is licensed, so
   it is declared first in the stack and loaded from /public/fonts if the
   files are present; Archivo carries the page until they are. */
/* Terminal pixel faces, from the same dotfiles that drive Ghostty. Framework
   themselves set small accents in a pixel font, so this is on-brief as well as
   personal. Pixel fonts only resolve cleanly at their design size, so every
   size below is pinned to 11px or 14px, never a rem.
   The files are Latin subsets: the full faces carry thousands of glyphs the
   page never sets, and were the two heaviest things on it. See fonts/README. */
@font-face{
  font-family:Gohu;font-style:normal;font-weight:400;font-display:swap;
  src:url("/fonts/GohuFont-14-latin.woff2") format("woff2");
}
@font-face{
  font-family:GohuSmall;font-style:normal;font-weight:400;font-display:swap;
  src:url("/fonts/GohuFont-11-latin.woff2") format("woff2");
}
@font-face{
  font-family:Cozette;font-style:normal;font-weight:400;font-display:swap;
  src:url("/fonts/CozetteVector-latin.woff2") format("woff2");
}
@font-face{
  font-family:Cozette;font-style:normal;font-weight:700;font-display:swap;
  src:url("/fonts/CozetteVectorBold-latin.woff2") format("woff2");
}

/* Graphik is Commercial Type's and licensed per project, so no file ships
   here. Only local() is named: a machine that has the face uses it, everybody
   else falls through to Wix Madefor without the browser asking for a file
   that was never going to be there and logging a 404 for it.

   With a licence, drop the woff2 into public/fonts and add the url() back:
       src:local("Graphik Regular"),url("/fonts/Graphik-Regular.woff2") format("woff2"); */
@font-face{
  font-family:Graphik;font-style:normal;font-weight:400;font-display:swap;
  src:local("Graphik Regular"),local("Graphik-Regular");
}
@font-face{
  font-family:Graphik;font-style:normal;font-weight:500;font-display:swap;
  src:local("Graphik Medium"),local("Graphik-Medium");
}
@font-face{
  font-family:Graphik;font-style:normal;font-weight:600;font-display:swap;
  src:local("Graphik Semibold"),local("Graphik-Semibold");
}

:root{
  /* Framework brand */
  --orange:#f45925;
  --orange-hover:#f8845d;
  --orange-press:#cf3502;
  --orange-tint:#fee5dd;

  /* funding green — the money is progress, not brand */
  --green:#12924b;
  --green-soft:#e6f4ec;

  /* surfaces — warm neutral, never pure white */
  --bg:#f3f2f2;
  --bg-alt:#fafaf9;
  --surface:#ffffff;
  --surface-sunk:#3d2e290f;
  --dark:#282524;
  --dark-2:#2a2422;

  /* ink */
  --ink:#2a2422;
  --ink-2:#4f4f4f;
  --muted:#6d6d6d;

  /* lines */
  --line:#dddddd;
  --line-strong:#bdbdbd;
  --bg-lid:#d9d9d6;

  /* radii, from Framework's scale */
  --r-sm:.25rem;
  --r-md:.375rem;
  --r-lg:.5rem;
  --r-xl:.75rem;
  --r-2xl:1rem;
  --radius:var(--r-lg);
  /* spacing rhythm, 4px base, as used on frame.work */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px;

  --wrap:1180px;
  /* The families vendored by scripts/fonts.mjs. Graphik (Commercial Type) is
     licensed, so it is only named here: drop the woff2 into public/fonts and
     the @font-face above picks it up with no other change. Wix Madefor is the
     shipped stand-in for it — same straight-sided rounds and flat terminals. */
  --font-display:"Wix Madefor Display";
  --font-sans:"Wix Madefor Text";
  --font-mono:"DM Mono";
  --sans:Graphik,var(--font-sans),"Helvetica Neue",Arial,sans-serif;
  --display:Graphik,var(--font-display),var(--font-sans),"Helvetica Neue",Arial,sans-serif;
  --mono:Gohu,var(--font-mono),"DM Mono",ui-monospace,Menlo,monospace;
  --mono-sm:GohuSmall,Gohu,var(--font-mono),"DM Mono",ui-monospace,Menlo,monospace;
  /* the 3D plates draw at fluid sizes, so they keep the scalable face */
  --mono-fluid:var(--font-mono),"DM Mono",ui-monospace,Menlo,monospace;
  --ease:cubic-bezier(.2,.7,.2,1);

  /* the sticky bar's height, in one place: the drawer, the scroll offset and
     the hero's first screen are all measured off it */
  --nav-h:56px;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:calc(var(--nav-h) + 10px);-webkit-text-size-adjust:100%}
/* No overflow rule on the page itself, deliberately.
   Clipping the root is the usual cure for a sideways drag, but on a phone
   panning and pinch-zoom are the same gesture: clip the page and it can no
   longer be zoomed into and moved around, which is worse than the drag it
   fixes. Anything wide is clipped where it lives instead — see .marquee. */
body{
  margin:0;background:var(--bg);color:var(--ink);
  min-height:100svh;display:flex;flex-direction:column;
  font-family:var(--sans);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* browser surfaces belong to the design too */
::selection{background:var(--orange);color:#fff}
:focus-visible{outline:2px solid var(--orange);outline-offset:2px;border-radius:var(--r-sm)}
:where(input,textarea){caret-color:var(--orange)}
/* Only the page's own bar is dressed. Everything that scrolls inside it — the
   bid sheet, a wide table — keeps the platform's own, which is the one that
   fades on a Mac, tracks a trackpad's momentum, and behaves the way the rest
   of that device does. */
@supports (scrollbar-color:auto){html{scrollbar-color:var(--line-strong) var(--bg)}}
html::-webkit-scrollbar{width:11px;height:11px}
html::-webkit-scrollbar-track{background:var(--bg)}
html::-webkit-scrollbar-thumb{background:var(--line-strong);border:3px solid var(--bg);border-radius:99px}
html::-webkit-scrollbar-thumb:hover{background:var(--muted)}

h1,h2,h3{margin:0 0 .5em;line-height:1.08;letter-spacing:-.025em;font-weight:600;
  font-family:var(--display);text-wrap:balance}
h1{font-size:clamp(2.4rem,5vw,3.9rem);letter-spacing:-.035em;max-width:15ch}
h2{font-size:clamp(1.75rem,3.2vw,2.6rem);letter-spacing:-.03em}
h3{font-size:1.05rem;letter-spacing:-.015em}
p{margin:0 0 1em;text-wrap:pretty}
a{color:inherit;text-underline-offset:.18em;text-decoration-thickness:from-font}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px}
.hero .wrap{max-width:1240px}
.wrap.narrow{max-width:760px}
.mono,.badge,.tag,.card-dims,.lid-foot,.spot-id,.spot-bid,.pill,
.lid-view,.cur-btn,.table th,.nav-visits,.raised-foot b,[data-countdown]{
  -webkit-font-smoothing:none;font-smooth:never}
.mono{font-family:var(--mono-sm);font-size:11px;letter-spacing:.08em;text-transform:uppercase;font-weight:400}
.money{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.muted{color:var(--muted)}
.hidden{display:none !important}
.right{text-align:right}
.sub{color:var(--ink-2);max-width:68ch;font-size:1.05rem}
.sub.wide{max-width:78ch}
.fineprint{font-size:.82rem;color:var(--muted);line-height:1.55}
.kicker{color:var(--muted);display:block;margin-bottom:10px}

/* buttons — Framework's are square-shouldered and confident */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:10px 20px;border-radius:999px;border:1px solid transparent;
  font-family:inherit;font-weight:500;font-size:.95rem;letter-spacing:-.005em;
  text-decoration:none;cursor:pointer;
  transition:background .18s var(--ease),border-color .18s var(--ease),color .18s var(--ease),transform .12s var(--ease)}
.btn-primary{background:var(--orange);color:#fff}
.btn-primary:hover{background:var(--orange-hover)}
.btn-primary:active{background:var(--orange-press);transform:translateY(1px)}
.btn-ghost{border-color:var(--line-strong);background:var(--surface);color:var(--ink)}
.btn-ghost:hover{border-color:var(--ink);background:var(--bg-alt)}
.btn-ghost:active{background:var(--surface-sunk);transform:translateY(1px)}
.btn-sm{padding:8px 16px;font-size:.86rem}
/* The one in the bar is thinner than a page button: it shares its height with
   the logo and the links, and a tall pill there makes the bar look packed. */
.nav-cta{padding:6px 15px;font-size:.85rem}
.btn.full{width:100%;margin-top:14px}
.btn[disabled]{opacity:.45;pointer-events:none}

/* ------------------------------------------------------------------
   Navigation — frame.work's own: a short sticky bar with full-width
   panels that drop out of the top-level items.
   ------------------------------------------------------------------ */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

.nav{position:sticky;top:0;z-index:60}


.nav-bar{background:#fff;border-bottom:1px solid var(--line)}
/* Glass once the page is under it. The colour is the page's own, so the blur
   reads as the page seen through it rather than a grey pane; the fallback for
   a browser without backdrop-filter is the solid white it already had. */
.nav-bar.is-lifted{background:rgba(255,255,255,.72);
  border-bottom-color:rgba(221,221,221,.7);
  box-shadow:0 1px 14px rgba(40,37,36,.08)}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .nav-bar.is-lifted{background:rgba(255,255,255,.62);
    -webkit-backdrop-filter:saturate(180%) blur(14px);
    backdrop-filter:saturate(180%) blur(14px)}
}
.nav-inner{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:28px;height:var(--nav-h)}
.brand{display:flex;align-items:center;gap:8px;text-decoration:none;
  font-family:Cozette,var(--mono),monospace;font-weight:400;font-size:13px;
  letter-spacing:-.02em;word-spacing:-.12em;
  -webkit-font-smoothing:none;font-smooth:never}
.brand b{font-weight:400}
@media (min-width:560px){.brand{font-size:19px}}

/* the four sections, in the middle of the bar */
.nav-links{display:flex;align-items:center;justify-content:center;gap:4px;font-size:.875rem}
.nav-top{display:inline-flex;align-items:center;text-decoration:none;
  font-family:inherit;font-size:.875rem;font-weight:500;color:var(--ink);letter-spacing:-.005em;
  padding:16px 14px;position:relative;transition:color .15s var(--ease)}
.nav-top:hover{color:var(--orange)}
.nav-top::after{content:"";position:absolute;left:14px;right:14px;bottom:10px;height:1.5px;
  background:var(--orange);transform:scaleX(0);transform-origin:left;
  transition:transform .22s var(--ease)}
.nav-top:hover::after{transform:scaleX(1)}

/* right cluster: the one primary action */
.nav-right{display:flex;align-items:center;justify-content:flex-end;gap:8px}

/* hamburger */
.nav-burger{display:none;flex-direction:column;justify-content:center;gap:4px;
  width:38px;height:38px;padding:0 9px;border:0;background:none;cursor:pointer;border-radius:var(--r-md)}
.nav-burger span{display:block;height:1.5px;background:var(--ink);border-radius:2px;
  transition:transform .22s var(--ease),opacity .18s var(--ease)}
.nav-burger:hover{background:var(--surface-sunk)}
.nav-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.nav-burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}

/* mobile drawer */
.mobile-menu{position:fixed;left:0;right:0;top:var(--nav-h);bottom:0;background:var(--bg);
  overflow-y:auto;padding:12px 0 40px;
  opacity:0;transform:translateY(-6px);transition:opacity .2s var(--ease),transform .22s var(--ease)}
.mobile-menu.is-open{opacity:1;transform:none}
.m-link{display:block;border-bottom:1px solid var(--line);text-decoration:none;color:var(--ink);
  padding:16px 2px;font-size:1.05rem;font-weight:500}
.m-link:hover{color:var(--orange)}
.mobile-menu .btn.full{margin-top:22px}

@media (max-width:1040px){
  .nav-inner{grid-template-columns:1fr auto}
  .nav-links{display:none}
  .nav-cta{display:none}
  .nav-burger{display:flex}
}
.cur{display:flex;border:1px solid var(--line-strong);border-radius:999px;overflow:hidden;background:var(--surface)}
.cur-btn{border:0;background:transparent;color:var(--muted);padding:7px 12px;cursor:pointer;
  font-family:var(--mono);font-size:14px;font-weight:500;transition:.15s var(--ease)}
.cur-btn:hover{color:var(--ink)}
.cur-btn.is-on{background:var(--ink);color:#fff}

/* the mark: four modules and a socket — this project's own, not Framework's */
.gear{flex:none;display:block;width:auto;height:17px}

/* hero — the machine is the backdrop, the copy sits on it */
/* A viewport tall at least, and taller if what is in it needs the room: the
   hero used to be capped and clipped, which on a wide screen let the pitch
   and the buttons spill out of it and land on the dark section below. */
.hero{position:relative;min-height:calc(100svh - var(--nav-h));display:flex;flex-direction:column;
  justify-content:center;padding:26px 0 24px;background:#fff;
  isolation:isolate}
/* the title sits off the nav the way brandmymac's does: 48px, 64px once
   there is room for it */
@media (min-width:768px){.hero{padding-top:34px}}
.hero-head{position:relative;z-index:2;text-align:center;max-width:1100px}
/* The live count sits on the right shoulder of the headline: a readout, not a
   line of copy, so it keeps the terminal face and the tabular figures and
   stays out of the centred column. */
.visits{display:flex;align-items:center;justify-content:flex-end;gap:7px;
  margin:0 0 10px;font-family:var(--mono);font-size:13px;color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.visits b{color:var(--ink);font-weight:600}
/* the live count: a green dot that breathes, the way a status light does */
.visits .live{display:inline-flex;align-items:center;gap:6px}
.visits .live i{width:7px;height:7px;border-radius:50%;background:#1a9b4a;
  box-shadow:0 0 0 0 rgba(26,155,74,.45);animation:live-dot 2.2s ease-out infinite}
.visits .visits-sep{color:var(--line-strong)}
.visits .hidden{display:none}
@keyframes live-dot{0%{box-shadow:0 0 0 0 rgba(26,155,74,.45)}70%{box-shadow:0 0 0 6px rgba(26,155,74,0)}100%{box-shadow:0 0 0 0 rgba(26,155,74,0)}}
@media (prefers-reduced-motion:reduce){.visits .live i{animation:none}}
@media (max-width:640px){.visits{font-size:12px;margin-bottom:14px}}
/* Cozette Bold: a pixel face with a genuine heavy weight. It resolves on
   whole multiples of its 13px design size, so the headline steps 26/39/52/65
   rather than scaling continuously, and the tracking is pulled in because a
   monospaced face sets far too loose at display size. */
.hero h1{font-family:Cozette,var(--mono),monospace;font-weight:400;
  /* a monospaced face carries a full advance for the space, so the words
     drift apart long before the letters do: close the gaps with
     word-spacing and keep the tracking just shy of collision */
  letter-spacing:-.03em;word-spacing:-.16em;
  -webkit-font-smoothing:none;font-smooth:never;
  font-size:26px;line-height:1.1;max-width:none;white-space:nowrap;margin:0 auto .34em}
@media (min-width:560px){.hero h1{font-size:39px}}
@media (min-width:900px){.hero h1{font-size:52px}}
@media (min-width:1320px){.hero h1{font-size:65px}}
.hero h1 .heart{color:var(--orange)}
/* One line on a desktop, where it fits. On a phone it breaks where the
   sentence does — after 'Your brand,' — rather than wherever the width runs
   out, which was splitting 'on my Framework' across two lines. */
.h1-br{display:none}
@media (max-width:640px){
  .hero h1{white-space:normal;letter-spacing:-.04em}
  .h1-br{display:inline}
}
.hero .lede{font-size:clamp(1.05rem,1.5vw,1.26rem);color:var(--ink-2);
  max-width:62ch;margin:0 auto 20px}


/* One line and a bar. The figure and the percentage are two halves of the
   same fact, so they sit on the same line at every width rather than
   stacking into three rows of chrome above the machine. */
/* As wide as the line beneath it and no wider: the countdown is the longest
   thing this block says, so the bar is a rule over that sentence rather than
   a divider drawn across the page. `max-content` is what measures it, and
   the clamp is what keeps it on a phone. */
.raised{width:max-content;max-width:100%;margin:0 auto}
.raised-row{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:0 0 7px}
.raised-num{display:flex;align-items:baseline;gap:9px;margin:0}
.raised-num b{font-family:var(--display);font-size:clamp(1.45rem,2.4vw,1.8rem);font-weight:600;letter-spacing:-.04em;
  line-height:1;color:var(--green)}
.raised-num span{color:var(--muted);font-size:.92rem}
.raised-pct{margin:0;font-size:.88rem;color:var(--green);font-weight:500}
/* The track has to read as a bar with nothing in it, not as nothing: ink at
   six per cent on white is invisible, and at $0 that is the whole thing. */
.bar{position:relative;height:8px;background:var(--line);border-radius:99px;overflow:hidden}
.bar-fill{height:100%;background:var(--green);border-radius:99px}
/* past the goal the bar keeps filling and marks where the goal actually was */
.bar.is-over .bar-fill{background:linear-gradient(90deg,var(--green) 0%,#1fb862 100%)}
.bar-goal{display:none}
.bar.is-over .bar-goal{display:block;position:absolute;top:-3px;bottom:-3px;
  left:var(--goal);width:2px;background:var(--bg);border-radius:2px;
  box-shadow:0 0 0 1px rgba(18,146,75,.45)}
.raised-foot{margin:10px 0 0;font-size:.84rem;color:var(--muted)}
.raised-foot b{font-family:var(--sans);font-size:.92rem;color:var(--ink);font-weight:600;
  font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;margin:0 .25em}
/* days, hours, minutes, seconds: the letters are labels, not figures, so they
   are smaller and quieter and carry the space that separates the pairs */
[data-countdown] i{font-style:normal;font-weight:400;font-size:.78em;
  color:var(--muted);margin:0 .42em 0 .1em;letter-spacing:0}
[data-countdown] i:last-child{margin-right:0}

.lede-2{font-size:1rem;color:var(--muted);margin-top:-12px}
/* the pitch under the machine: one line of what this is, one of where it goes */
.stage-copy{max-width:660px;text-align:center;margin:6px auto 26px}
.stage-copy .lede{margin-bottom:.5em}
.stage-copy .lede-2{margin-top:0}
.cta-row{position:relative;z-index:2;display:flex;gap:12px;flex-wrap:wrap;
  justify-content:center;margin:0 0 18px}

/* the machine, full-bleed behind everything */
.hero-sell{text-align:center;max-width:70ch;margin-inline:auto}
.hero-sell p{font-size:1rem;color:var(--ink-2);margin:0 0 14px}
.cta-row{margin-top:0;padding-bottom:6px}
/* The stage is a width-driven box: its height falls out of the aspect ratio,
 * so the machine keeps the same shape from a phone to a wide desktop and the
 * page never reflows when the WebGL scene arrives. 4/3 leaves just enough
 * slack under the 1.295 lid for the contact shadow. */
/* The machine gets its room first: full size wherever there is height for it,
   and only trimmed on a screen too short to stand it up. The height falls out
   of the 4/3 ratio, so the bound is written against the width. Nothing in the
   hero is allowed to sit on top of it — the copy and the buttons follow it in
   the flow and the hero grows to hold them. */
/* The machine is what people came for: the copy above it is trimmed to the
   least that still introduces it, and the stage starts as high as it can, so
   more of the cover lands above the fold. */
.hero-stage{position:relative;z-index:0;width:100%;max-width:min(900px,calc(76svh * 4 / 3));
  flex:0 0 auto;aspect-ratio:4/3;margin:4px auto 2px;
  display:flex;align-items:center;justify-content:center}
/* the fallback board fits the stage rather than spilling out of it */
.hero-stage .lid{width:min(95%,860px);height:auto}
/* the machine sits on something: a soft ellipse under the lid */
.hero-stage .lid::after{content:'';position:absolute;z-index:-1;
  left:7.5%;right:7.5%;bottom:-5%;height:5.5%;border-radius:50%;
  background:rgba(0,0,0,.12);filter:blur(14px);pointer-events:none}
.hero .lid-views{margin:0 auto;width:max-content;display:inline-grid}
.hero .lid-caption{margin-bottom:14px}
.tagline{font-size:clamp(1.02rem,1.45vw,1.22rem);color:var(--ink-2);
  max-width:52ch;margin:0 auto 14px}
.hero-sub{text-align:center;max-width:1100px;margin-top:6px}
.hero-sub .lede{margin-left:auto;margin-right:auto}

/* the argument, below the fold */
.beside{background:var(--dark);color:#f3f2f2;padding:clamp(96px,15vw,190px) 0}
/* the line sits in the middle of the dark band: the marquee carries the space
   under it, so it has to match the padding above rather than the smaller gap
   it uses between ordinary sections */
.beside .marquee{margin-top:clamp(96px,15vw,190px)}
/* the marquee IS the section's bottom edge: it runs flush to it, so the band
   reads as the boundary between this section and the next rather than as one
   more thing sitting inside it */
.beside:has(.marquee){padding-bottom:0}
.beside-inner{max-width:1000px;text-align:center}
.beside h2{color:#fff;font-size:clamp(2rem,5.2vw,3.9rem);letter-spacing:-.045em;
  line-height:1.04;margin:0 auto;max-width:20ch}
.beside h2 span{color:var(--orange)}

/* the 3D stage: canvas over the flat board, flat board wins on focus.
 * `has-3d` lands as soon as WebGL has answered for itself, so the flat board
 * is never seen behind the machine during the seconds the scene takes to
 * build. It stays in the document, and focus still brings it back, because
 * it is the keyboard route to every spot. */
/* One lid, never two. The flat board is hidden by default rather than hidden
 * once the canvas announces itself: relying on a class to arrive means any
 * hitch in that handoff shows both at once. It comes back only when 3D is
 * genuinely unavailable, or when a keyboard reaches into it.
 *
 * It stays in the DOM either way. It is the accessible control surface, and
 * the canvas forwards every click down to these buttons and reads the board
 * from their data attributes. */
.hero-stage .lid{opacity:0;pointer-events:none;transition:opacity .3s var(--ease)}

.hero-stage .lid:focus-within{opacity:1;pointer-events:auto}
/* Not in the flat view: there the board is the view, and the machine showing
   faintly through it as soon as a spot takes focus reads as a render that
   failed to go away. The rule below it is less specific than this one, so
   the exception has to live here. */
.hero-stage.is-3d:not(.flat) .lid:focus-within ~ .lid3d-canvas{opacity:.12}
/* No machine, for whatever reason: the flat board is the page again, and it
   has to beat the rules above whichever order the classes landed in. */
.hero-stage.no-3d .lid{opacity:1;pointer-events:auto}
.hero-stage.no-3d .lid3d-canvas{display:none}
/* The flat view, asked for rather than fallen back to: the same board the
   machine has no choice about showing, straight on. The machine floats in a
   frame of its own making and the board does not, so the room it needs above
   and below is given to it. */
.hero-stage.flat{padding:clamp(18px,3vw,44px) 0}
.hero-stage.flat .lid{opacity:1;pointer-events:auto}
.hero-stage.flat .lid3d-canvas{opacity:0;pointer-events:none}
.lid3d-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;
  opacity:0;transition:opacity .55s var(--ease)}
.lid3d-canvas.is-ready{opacity:1}

/* auction closed */
.btn.is-disabled{pointer-events:none;opacity:.45}
.is-closed .card .btn{opacity:.45;pointer-events:none}
.is-closed .table .btn{opacity:.45;pointer-events:none}
.is-closed .spot{cursor:default}
.is-closed .spot:hover{background:rgba(255,255,255,.12);border-color:rgba(28,23,21,.62)}
.is-closed [data-closed-copy]{color:var(--orange-press);font-weight:500}

/* countdown */
.eyebrow-sep{width:1px;height:11px;background:var(--line-strong);display:inline-block}
[data-countdown]{font-variant-numeric:tabular-nums}
.is-closed [data-countdown]{color:var(--orange-press)}

/* view switch */
/* The view switch, in the shape brandmymac uses for its currency toggle: a
   sunk hairline track with a white pill riding on it, a soft shadow and a
   hair-thin ring. The pill is one element that slides, rather than a
   background appearing on whichever button is on — so the switch moves. */
/* Two equal columns, not two content-width buttons: the pill that slides is
   half the track, so the moment one label is longer than the other it stops
   lining up with either of them. A grid makes both as wide as the longer
   label and the halves are honest again. */
.lid-views{position:relative;display:inline-grid;grid-auto-flow:column;
  grid-auto-columns:1fr;padding:3px;border:0;
  border-radius:999px;background:rgba(221,221,221,.5)}
/* One pill on a track of --n equal columns, moved a whole column at a time.
   Written for the count rather than for two, so a third view is a button and
   a number rather than a rewrite. */
.lid-views{--n:3}
.lid-views::before{content:'';position:absolute;top:3px;bottom:3px;left:3px;
  width:calc((100% - 6px) / var(--n));border-radius:999px;background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.14),0 0 0 1px rgba(0,0,0,.1);
  transition:transform .3s var(--ease)}
.lid-views:has(.lid-view:nth-child(2).is-on)::before{transform:translateX(100%)}
.lid-views:has(.lid-view:nth-child(3).is-on)::before{transform:translateX(200%)}
.lid-view{position:relative;z-index:1;min-width:106px;
  border:0;background:none;color:var(--ink-2);cursor:pointer;
  /* set like a segmented control rather than a label: sentence case at a
     size that renders on its own pixels, and a weight that holds up on a
     phone. Small tracked capitals went soft at 11px. */
  font-family:var(--sans);font-weight:600;font-size:13px;letter-spacing:-.01em;
  padding:8px 16px;border-radius:999px;
  -webkit-font-smoothing:antialiased;
  transition:color .2s var(--ease)}
.lid-view:hover{color:var(--ink)}
.lid-view.is-on{color:var(--ink)}
.lid-view:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
@media (max-width:640px){.lid-view{padding:9px 12px;min-width:92px;font-size:13px}}
@media (prefers-reduced-motion:reduce){.lid-views::before{transition:none}}
/* the line under the switch: what this view is, then what to do with it */
.lid-caption{display:flex;align-items:center;justify-content:center;gap:9px;
  margin:10px auto 0;font-size:.86rem;color:var(--muted);text-align:center}
.lid-caption-lead{font-family:var(--mono);font-size:.62rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--orange-press);
  border:1px solid var(--line-strong);border-radius:999px;padding:3px 8px;flex:none}

/* final look: the finished lid — stickers only, no auction chrome */
.spot-sticker{display:none;font-weight:600;font-size:clamp(.6rem,.95vw,.92rem);
  letter-spacing:-.025em;line-height:1.05;text-align:center;color:var(--ink);
  max-width:100%;overflow-wrap:anywhere}
/* A sticker is cut to the area it was bought at, so it expands until it
   touches the sides of the spot — left and right for a wide logo, top and
   bottom for a tall one, whichever its proportions decide. */
.spot-sticker img{width:100%;height:100%;object-fit:contain;display:block;margin:0 auto}
.spot-sticker i{font-style:normal;font-weight:400;color:#a09a97;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.06em;
  text-transform:uppercase}
/* A mark on the board itself: a spot that sent one wears it instead of its
   name, and the artwork being placed in the dialog appears here the same way
   it appears on the machine. */
.lid:not(.final) .spot:has(.spot-sticker img) .spot-brand{display:none}
.lid:not(.final) .spot:has(.spot-sticker img) .spot-sticker{
  order:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;flex:1 1 auto;min-height:0;width:100%;overflow:hidden}
.spot-sticker img{transform-origin:50% 50%}
/* The mark takes the room that is left after the caption, not all of it:
   without this the artwork claims the full height of the area and the price
   along the bottom ends up printed over it. */
.spot-sticker:has(img){min-height:0}
.spot-sticker img{flex:1 1 auto;min-height:0;max-height:100%}
/* The name under the mark, the way the machine sets it: quieter than the
   artwork, on one line where it fits and wrapped where it does not. */
.sticker-name{flex:0 0 auto;max-width:100%;font-size:10px;font-weight:600;
  line-height:1.1;letter-spacing:-.01em;color:var(--ink);text-align:center;
  overflow-wrap:anywhere}
@media (min-width:640px){.sticker-name{font-size:12px}}
.lid.final .spot-id,.lid.final .spot-brand,.lid.final .spot-bid{display:none}
.lid.final .spot-sticker{display:flex;align-items:center;justify-content:center;
  flex:1;align-self:stretch;width:100%;min-width:0}
/* A sticker on the finished cover is vinyl on metal, not a card laid on it:
   no panel behind it and no border round it, so the artwork is the only
   thing on the lid. */
.lid.final .spot{background:transparent;border-color:transparent;box-shadow:none}
/* an unsold spot on the finished lid is bare cover: nothing to see until
   you point at it, and then it offers itself */
.lid.final .spot:has(.spot-sticker i){background:transparent;
  border-style:dashed;border-color:transparent;box-shadow:none}
.lid.final .spot:has(.spot-sticker i) .spot-sticker i{opacity:0;transition:opacity .15s var(--ease)}
.lid.final .spot:has(.spot-sticker i):hover,
.lid.final .spot:has(.spot-sticker i):focus-visible{background:rgba(255,255,255,.34);
  border-color:var(--orange)}
.lid.final .spot:has(.spot-sticker i):hover .spot-sticker i,
.lid.final .spot:has(.spot-sticker i):focus-visible .spot-sticker i{opacity:1}
.lid.final:hover .spot{transform:none}
/* The flat board: the lid itself, with the spots sitting on it where they
 * sit on the machine. 6 columns x 3 rows, the milled wordmark at row 2,
 * cols 3-4. This is the no-JS control surface and it is also what stands in
 * for the few seconds before the WebGL machine is ready, so it has to read
 * as a lid on its own. */
.lid{
  position:relative;aspect-ratio:356.58/290.2;
  display:grid;grid-template-columns:repeat(6,minmax(0,1fr));
  grid-template-rows:minmax(0,1fr) minmax(0,.9fr) minmax(0,1fr);
  /* The extra padding clears the hinge cover across the back. It is measured
     off the drawing: the cover is 290.2mm deep and the hinge band takes 24 of
     them, so the room it needs scales with the board's height, not its width
     the way a percentage would. */
  /* More room along the top and bottom edges than down the sides: a real
     cover has a margin the stickers do not run into, and the prices now sit
     along the top of each area where they were closest to running out of
     it. */
  gap:8px;padding:18px 8px calc(18px + 24 / 290.2 * 100%);border-radius:18px;
}
@media (min-width:640px){.lid{gap:12px;padding:30px 16px calc(30px + 24 / 290.2 * 100%);border-radius:22px}}
.lid-art{position:absolute;inset:0;width:100%;height:100%;
  border-radius:inherit;pointer-events:none}

/* The areas are cut into the cover, not laid on top of it: no fill, so the
   aluminium is what you see inside them and a sticker sits on metal rather
   than on a white card. Only the pointer fills one in. */
.spot{
  position:relative;border:1px dotted rgba(42,36,34,.42);border-radius:12px;
  background:transparent;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  cursor:pointer;padding:8px 6px;text-align:center;overflow:hidden;
  /* a button carries its platform's colour unless told otherwise, and on an
     iPhone that is blue; the board is ink, like the machine */
  color:var(--ink);font:inherit;
}
.spot:hover{background:rgba(255,255,255,.5);border-color:var(--orange)}
/* Aiming at one: the area being bid on is lit and the rest of the board
   stands back, so the dialog and the cover are about the same square. */
.lid .spot{transition:opacity .2s var(--ease),border-color .2s var(--ease),
  background .2s var(--ease),box-shadow .2s var(--ease)}
.lid.aiming .spot{opacity:.32}
/* Lit by its edge, not by a fill: the area is a window onto the cover, and
   filling it in hides the one thing being bid on. */
.lid.aiming .spot.is-target{opacity:1;border-style:solid;border-color:var(--orange);
  box-shadow:0 0 0 3px var(--orange-tint)}
/* Its price goes while it is being bid on: the dialog is already asking
   about that, and the area is given over to the artwork. */
.lid.aiming .spot.is-target .spot-bid{display:none}
/* a spot that is taken is shown by what is on it, not by a line round it */
.spot.taken{border-color:transparent;background:transparent}
/* The number was a label on a form. The area is identified by what is on it
   and what it costs, and the board is quieter without ten of them. */
.spot-id{display:none}
/* The price first and the artwork under it: a mark cut to its area runs to
   the edges, so a figure set beneath it has nowhere to sit that is not on
   top of the sticker. Along the top it is clear of the artwork, and the
   board still reads as a row of figures rather than ten stacked cards. */
.lid:not(.final) .spot-bid{order:0;margin-bottom:auto}
/* An area nobody holds says its size in the middle of itself with the price
   right under it, the pair centred where a sticker would sit. A held area
   keeps its price along the top edge, clear of the artwork. */
.lid:not(.final) .spot-brand{order:2;flex:1 1 auto;min-height:0;
  display:flex;align-items:center;justify-content:center;text-align:center}
.lid:not(.final) .spot:not(.taken) .spot-brand{flex:0 0 auto}
.lid:not(.final) .spot:not(.taken) .spot-bid{order:3;margin:2px 0 0}
.spot-brand{font-weight:700;font-size:10px;line-height:1.15;
  /* the same stack the machine paints its plates in, so a name or a size
     reads alike on the flat board and on the cover */
  font-family:Graphik,Archivo,"Helvetica Neue",Arial,sans-serif;
  letter-spacing:-.015em;max-width:100%;overflow-wrap:anywhere;hyphens:auto}
.spot-bid{font-family:var(--mono);font-size:13px;line-height:1.15;
  color:var(--orange-press);font-variant-numeric:tabular-nums}
/* one step up once the board is wide enough to carry it, the way the spots
   themselves step from 8px to 16px of board padding */
@media (min-width:640px){
  .spot-id{font-size:10px}
  .spot-brand{font-size:13px}
  .spot-bid{font-size:17px}
}
/* Hovering a held area offers the sponsor's site: a small pill in a quiet
   blue that fades up from just below its resting place and back down when
   the pointer leaves. It only exists where there is somewhere to go. */
.spot-visit{position:absolute;z-index:5;left:50%;bottom:6px;transform:translate(-50%,6px);
  opacity:0;pointer-events:none;
  font:600 10px/1 var(--sans);letter-spacing:-.01em;white-space:nowrap;
  color:#1e4fd8;background:rgba(30,79,216,.1);border:1px solid rgba(30,79,216,.22);
  padding:5px 9px;border-radius:999px;
  transition:opacity .22s var(--ease),transform .22s var(--ease)}
.spot.taken[data-url]:hover .spot-visit,.spot.taken[data-url]:focus-visible .spot-visit{
  opacity:1;transform:translate(-50%,0);pointer-events:auto}
.spot-visit:hover{background:rgba(30,79,216,.16)}
@media (min-width:640px){.spot-visit{font-size:12px;padding:6px 11px;bottom:8px}}
.lid.final .spot-visit{display:none}
@media (prefers-reduced-motion:reduce){.spot-visit{transition:none}}
.logo-slot{position:relative;grid-row:2;grid-column:3/5;display:flex;align-items:center;justify-content:center}
/* Milled into the cover, not printed on it: the same washed grey the machine
   renders it in, sized off the slot it sits in rather than a fixed pixel
   count, so it holds its place as the lid scales. */
.logo-cog{width:min(64%,84px);height:auto;color:#8c8681;opacity:.85;display:block}

/* sections */
.section{padding:88px 0}
.section.alt{background:var(--bg-alt)}
/* main section titles sit on the centre line */
.section > .wrap > h2,
.section > .wrap > .sub,
.sec-head > div > h2,
.sec-head > div > .sub{text-align:center;margin-inline:auto}
.sec-head{display:flex;flex-direction:column;align-items:center;gap:22px;margin-bottom:38px}
.sec-head > div:not(.tabs){width:100%}
.tabs{display:inline-flex;width:max-content;align-self:center;flex:0 0 auto;
  margin-inline:auto;border:1px solid var(--line-strong);
  border-radius:999px;overflow:hidden;background:var(--surface)}
.tab{border:0;background:transparent;padding:10px 17px;cursor:pointer;font-family:inherit;
  font-size:.86rem;font-weight:500;color:var(--muted);transition:.15s var(--ease)}
.tab:hover{color:var(--ink)}
.tab.is-on{background:var(--ink);color:#fff}

/* spot cards */
.grid-spots{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:var(--sp-4)}
.card{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  padding:var(--sp-5);display:flex;flex-direction:column;gap:var(--sp-3);
  transition:border-color .16s var(--ease),box-shadow .16s var(--ease)}
.card:hover{border-color:var(--ink);box-shadow:0 1px 2px rgba(40,37,36,.06)}
.card:focus-within{border-color:var(--ink)}
.card-top{display:flex;justify-content:space-between;align-items:center}
.badge{font-family:var(--mono-sm);font-size:11px;letter-spacing:.08em;padding:3px 8px;border-radius:var(--r-sm);
  border:1px solid var(--line-strong);color:var(--muted)}
.badge.L{background:var(--ink);color:#fff;border-color:var(--ink)}
.badge.M{background:var(--orange-tint);color:var(--orange-press);border-color:transparent}
/* the bid that is standing on the board, and the ones that got there */
.badge-top{background:var(--green-soft);color:var(--green);border-color:transparent}
.card h3{margin:0;font-size:.98rem;font-weight:600;letter-spacing:-.01em}
.card-dims{font-family:var(--mono-sm);font-size:11px;color:var(--muted);letter-spacing:.04em}
.card-dims b{color:var(--ink);font-weight:500;
  border:1px solid var(--line-strong);border-radius:var(--r-xs,3px);padding:1px 5px;margin-right:5px}
.card-bid{display:flex;align-items:baseline;gap:8px;margin-top:auto;
  padding-top:var(--sp-3);border-top:1px solid var(--line)}
.card-bid b{font-size:1.4rem;letter-spacing:-.035em;font-weight:600}
.card-holder{font-size:.85rem;color:var(--muted)}
/* a mark sits on the card's own left edge, in line with the name above it */
/* The handle sits under the mark, not beside it: side by side it read as a
   second sponsor rather than as the same one's address. */
.holder{display:flex;flex-direction:column;align-items:flex-start;
  justify-content:center;gap:4px;width:100%}
/* Tall enough to be a logo rather than a favicon, and big enough to be a tap
   target: a sponsor's mark is the link to their site and it should look like
   one is worth hitting. */
.holder img{width:auto;height:46px;max-width:190px;object-fit:contain;
  object-position:left center;flex:none;display:block}
.card-holder{text-align:left}
.table .holder img{height:24px;max-width:140px}
.card-holder b{color:var(--ink);font-weight:500}
.pending{font-family:var(--mono-sm);font-size:11px;color:var(--orange-press);letter-spacing:.05em}

/* stepping through the auction, one bid at a time */
.stepper{display:none;align-items:center;gap:14px;flex-wrap:wrap;justify-content:center;
  margin:0 0 22px;padding:12px 16px;border:1px solid var(--line);
  border-radius:999px;background:var(--surface);width:max-content;margin-inline:auto}
.stepper.is-on{display:flex}
.stepper button{border:1px solid var(--line-strong);background:var(--surface);color:var(--ink);
  width:32px;height:32px;border-radius:50%;cursor:pointer;font:inherit;line-height:1;
  display:grid;place-items:center;transition:.15s var(--ease)}
.stepper button:hover:not(:disabled){border-color:var(--ink)}
.stepper button:disabled{opacity:.35;cursor:default}
.stepper .step-play{width:auto;border-radius:999px;padding:0 16px;font-size:.86rem;font-weight:500}
.step-read{font-size:.88rem;color:var(--ink-2);min-width:190px;text-align:center}
.step-read b{font-weight:600}
.step-count{font-family:var(--mono-sm);font-size:11px;color:var(--muted);
  -webkit-font-smoothing:none}
.step-bar{width:100%;height:3px;background:var(--surface-sunk);border-radius:99px;overflow:hidden;
  max-width:420px;margin:0 auto 26px}
.step-bar i{display:block;height:100%;width:100%;background:var(--orange);border-radius:99px;
  transform-origin:left center;transform:scaleX(0);transition:transform .45s var(--ease)}

/* history filters */
.hist-filters{display:flex;align-items:center;justify-content:center;gap:12px;
  flex-wrap:wrap;margin:0 0 20px}
/* The platform's own arrow is drawn for a square field and sits badly in a
   pill, hard against the right edge. Ours is part of the field: a chevron in
   the ink colour with room around it. */
.hist-filters select{font:inherit;font-size:.86rem;padding:8px 34px 8px 14px;border-radius:999px;
  border:1px solid var(--line-strong);background:var(--surface);color:var(--ink);cursor:pointer;
  max-width:260px;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none' stroke='%236d6d6d' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;background-size:10px 6px}
.hist-filters select:hover{border-color:var(--ink)}
.hist-sort .tab{padding:8px 15px}
.hist-shown{font-size:11px;color:var(--muted);-webkit-font-smoothing:none}

/* bid history: the artwork as submitted, at the sticker's own proportions */
/* The artwork stands on the page as itself: a tile behind it was the lid's
   aluminium, and in a table it only made every logo look like it came with a
   grey rectangle. */
/* Centred in a box of one size, so a row of marks of every proportion reads
   as a column rather than as ten logos each starting somewhere else. */
.hist-art{display:flex;align-items:center;justify-content:center;
  width:76px;height:30px}
.hist-art img{max-width:100%;max-height:100%;object-fit:contain;display:block}
.hist-art-none{font-family:var(--mono-sm);font-size:10px;color:var(--muted);
  -webkit-font-smoothing:none}
/* Who holds it, as one thing: the mark and the name are the same answer, and
   two columns made them read as two facts about different people. */
.hist-held,.hist-held > a{display:flex;align-items:center;gap:12px;
  text-decoration:none;color:inherit}
.hist-held .hist-art{flex:none}
.hist-held > a:hover{color:var(--orange-press)}
.hist-held > a:hover img{opacity:.82}

/* the board table is prose, not telemetry: text face throughout */
.table,.table th,.table td{font-family:var(--sans);-webkit-font-smoothing:antialiased}
.table th{letter-spacing:.04em;text-transform:none;font-size:.8rem}
.table td{font-size:.92rem}
.table .card-dims{font-family:var(--sans);font-size:.86rem;letter-spacing:0}
.table .card-dims b{font-family:var(--mono-sm);font-size:11px}
/* The mark is a link: it says so on hover and it is a comfortable size to
   hit, rather than a 28px image you have to aim at. */
.holder a{display:inline-flex;align-items:center;gap:8px;text-decoration:none;
  color:inherit;cursor:pointer;border-radius:var(--r-sm);
  padding:4px 6px;margin:-4px -6px;min-height:44px;
  transition:background .15s var(--ease),opacity .15s var(--ease)}
.holder a:hover{color:var(--orange-press);background:var(--bg-alt)}
.holder a:hover img{opacity:.86}
.holder a:focus-visible{outline:2px solid var(--orange);outline-offset:1px}
/* in a table row the mark stays small and the padding would push the rows out */
.table .holder a{min-height:0;padding:2px 4px;margin:-2px -4px}
.holder-x{font-family:var(--mono-sm);font-size:11px;letter-spacing:.04em;
  color:var(--muted);text-decoration:none}
.holder-x:hover{color:var(--orange-press)}
.table .holder{align-items:flex-start;gap:4px}

/* table */
.table{width:100%;border-collapse:collapse;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);overflow:hidden}
.table th{font-family:var(--mono-sm);font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);text-align:left;padding:13px 16px;border-bottom:1px solid var(--line);font-weight:500}
.table td{padding:14px 16px;border-bottom:1px solid var(--line);font-size:.92rem;vertical-align:middle}
.table tr:last-child td{border-bottom:0}
.table tr:hover td{background:var(--bg-alt)}

/* A five-column table has nowhere to go on a 390px screen. Below the fold of
   a phone it stops being a table: each row is a card, and each cell carries
   the column heading it just lost, so nothing has to be scrolled sideways to
   be read. */
@media (max-width:760px){
  .table{border:0;background:none;border-radius:0}
  .table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .table tr{display:block;background:var(--surface);border:1px solid var(--line);
    border-radius:var(--r-lg);padding:4px 14px;margin-bottom:10px}
  .table tr:last-child{margin-bottom:0}
  .table tr:hover td{background:none}
  .table td{display:flex;align-items:center;justify-content:space-between;gap:16px;
    padding:11px 0;text-align:left;border-bottom:1px solid var(--line)}
  .table tr td:last-child{border-bottom:0}
  .table td::before{content:attr(data-label);flex:none;color:var(--muted);
    font-family:var(--mono-sm);font-size:10px;letter-spacing:.1em;text-transform:uppercase}
  .table td.right{text-align:right}
  .table td.right > *{margin-left:auto}
  .table td > *{min-width:0}
  .table .btn{width:100%}
  .table td:has(.btn)::before{display:none}
  .table td:has(.btn){padding-top:12px}
  .table .holder{align-items:flex-end}
}

/* steps */
.steps{list-style:none;counter-reset:step;margin:var(--sp-6) auto 0;padding:0;max-width:62ch;text-align:left}
.steps li{counter-increment:step;padding:var(--sp-6) 0 var(--sp-6) 64px;
  border-top:1px solid var(--line);position:relative}
.steps li:last-child{border-bottom:1px solid var(--line)}
.steps li::before{content:counter(step);position:absolute;left:0;top:22px;
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:var(--ink);color:#fff;font-family:var(--mono);
  font-size:14px;font-weight:400;line-height:1}
.steps h3{margin:0 0 var(--sp-1);font-size:1.05rem}
.steps p{margin:0;color:var(--ink-2);font-size:.95rem}

/* the bag reads as a receipt, not a terminal: labels in the text face */
.bag .mono,.bag-head .mono,.bag-group-head .mono,.bag-item-main .mono{
  font-family:var(--sans);font-size:.8rem;font-weight:600;letter-spacing:.02em;
  -webkit-font-smoothing:antialiased}
.bag-item-main p.mono{font-weight:400;color:var(--muted);text-transform:none;
  letter-spacing:0;font-size:.9rem}

/* bag / checkout */
.bag{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);margin-top:var(--sp-6);
  max-width:760px;margin-inline:auto;padding:0 var(--sp-5) var(--sp-5)}
.bag-head{display:flex;justify-content:space-between;align-items:center;gap:16px;
  padding:17px 0;border-bottom:1px solid var(--line)}
.bag-item{display:grid;grid-template-columns:96px 1fr auto;gap:18px;padding:22px 0;border-bottom:1px solid var(--line)}
/* Framework shoot on white, so the tile is the paper the photograph is on
   rather than the dark plate the drawn lid needed behind it. */
.bag-thumb{background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-md);aspect-ratio:1;overflow:hidden;
  display:flex;align-items:center;justify-content:center}
.bag-thumb img{width:100%;height:100%;object-fit:contain;display:block}
.bag-item-main h3{margin:8px 0 4px;font-size:1.06rem}
.tag{display:inline-block;font-family:var(--mono-sm);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  background:var(--orange);color:#fff;padding:3px 8px;border-radius:var(--r-sm)}
.tag-quiet{background:#eaf5f5;color:#3f5a5a;margin-left:8px}
.bag-blurbs{list-style:none;padding:0;margin:10px 0 0;color:var(--muted);font-size:.88rem}
.bag-blurbs li{padding-left:14px;position:relative}
.bag-blurbs li::before{content:"·";position:absolute;left:3px}
.bag-item-price{font-size:1.15rem;font-weight:600;white-space:nowrap;letter-spacing:-.02em}
.bag-details{padding:6px 0}
.bag-group{padding:14px 0;border-bottom:1px solid var(--line)}
.bag-group-head{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:8px;color:var(--muted)}
.bag-group-head .money{color:var(--ink);font-family:var(--mono);font-size:14px}
.bag-row{display:flex;justify-content:space-between;gap:16px;padding:5px 0;font-size:.92rem}
.bag-row .money,.bag-row .muted:last-child{font-family:var(--mono);font-size:14px}
.bag-row-label b{font-weight:500}
.row-link{text-decoration:underline;text-decoration-color:var(--line-strong);
  text-underline-offset:.2em;transition:color .15s var(--ease)}
.row-link:hover{color:var(--orange-press);text-decoration-color:currentColor}
.bag-totals{padding:16px 0 4px;border-bottom:1px solid var(--line)}
.bag-total{display:flex;justify-content:space-between;padding:7px 0;font-size:.95rem}
.bag-total .money{font-family:var(--mono);font-size:14px}
.bag-total.strong{font-size:1.14rem;font-weight:600;border-top:1px solid var(--line);margin-top:8px;padding-top:14px}
.bag-total.strong .money{font-family:var(--sans);font-size:1.14rem;letter-spacing:-.025em}
.bag .btn.full{margin:18px 0 6px}

/* faq */
.faq{border-top:1px solid var(--line-strong);margin-top:24px}
.faq details{border-bottom:1px solid var(--line-strong)}
.faq summary{cursor:pointer;list-style:none;padding:21px 0;font-weight:500;font-size:1.05rem;
  letter-spacing:-.015em;display:flex;justify-content:space-between;gap:20px;align-items:center}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--orange-press)}
.faq summary::after{content:"";flex:none;width:11px;height:11px;
  background:currentColor;color:var(--orange);
  -webkit-mask:var(--plus) center/contain no-repeat;mask:var(--plus) center/contain no-repeat;
  transition:transform .25s var(--ease)}
.faq{--plus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 11'%3E%3Cpath d='M5.5 0v11M0 5.5h11' stroke='%23000' stroke-width='1.4'/%3E%3C/svg%3E")}
.faq details[open] summary::after{transform:rotate(135deg)}
/* 0fr -> 1fr animates the track, not the box's own height */
.faq-body{display:grid;grid-template-rows:1fr;min-height:0}
.faq-body > div{overflow:hidden;min-height:0}
html.js .faq-body{grid-template-rows:0fr;transition:grid-template-rows .34s var(--ease)}
html.js .faq details.is-open .faq-body{grid-template-rows:1fr}
.faq p{color:var(--ink-2);padding-bottom:21px;margin:0;max-width:70ch}


/* bid confirmation */
.bid-ok{background:var(--bg-alt);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px;margin:18px 0 0;font-size:.9rem;line-height:1.5}
.card .btn{margin-top:0;width:100%}
.card-holder .pending{margin-top:4px}

/* who's carrying it */
.person{display:grid;grid-template-columns:112px 1fr;gap:28px;align-items:start}
.person-photo{width:112px;height:112px;border-radius:50%;overflow:hidden;flex:none;
  background:none;border:0;display:flex;align-items:center;justify-content:center}
.person-photo img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
.person-photo span{font-family:var(--mono);font-size:1.9rem;color:var(--muted);letter-spacing:.02em}
.person h2{margin-bottom:.35em}
.person p{color:var(--ink-2);font-size:1.03rem;max-width:64ch}
.person-links{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px;padding:0;list-style:none}
.person-links a{display:inline-flex;align-items:center;gap:8px;text-decoration:none;
  border:1px solid var(--line-strong);background:var(--surface);color:var(--ink);
  padding:8px 14px;border-radius:var(--r-lg);font-size:.88rem;
  transition:border-color .18s var(--ease),color .18s var(--ease),background .18s var(--ease)}
.person-links a:hover{border-color:var(--ink);background:var(--bg)}
.person-links svg{width:14px;height:14px;flex:none;color:var(--muted)}
.person-links a:hover svg{color:var(--orange)}

body > main{flex:1 0 auto}
body > .footer{margin-top:auto}

/* legal pages */
.legal{padding:80px 0 120px}
.legal .wrap{max-width:760px}
.legal h1{font-family:var(--display);font-size:clamp(1.9rem,4vw,2.7rem);letter-spacing:-.035em;
  white-space:normal;margin-bottom:.3em}
.legal .updated{font-family:var(--mono-sm);font-size:11px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-bottom:52px;-webkit-font-smoothing:none}
.legal h2{font-size:1.2rem;margin:56px 0 .65em}
.legal p,.legal li{color:var(--ink-2);max-width:70ch;line-height:1.72}
.legal p{margin:0 0 1.35em}
.legal ul{padding-left:20px;margin:0 0 1.6em}
.legal li{margin-bottom:.7em}
.legal .note{background:var(--bg-alt);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-5);margin:40px 0 48px;font-size:.92rem;line-height:1.6}

/* footer */
.footer{padding:26px 0 22px;background:var(--dark);color:#c9c3c0;border-top:0}
.footer .brand{color:#f3f2f2}
.footer .fineprint{color:#8f8884;font-size:.72rem;line-height:1.5;max-width:92ch}
.footer .fineprint a{color:#c9c3c0}
.footer-inner{display:flex;justify-content:space-between;align-items:center;
  gap:16px;margin-bottom:10px;flex-wrap:wrap}
.footer .brand{font-size:15px}
.footer .brand .mono{font-size:10px;letter-spacing:.1em}
.footer .gear{height:16px}
.footer nav{display:flex;gap:16px;font-size:.82rem;flex-wrap:wrap}
.footer nav a{color:#a9a29e;text-decoration:none}
.footer nav a:hover{color:var(--orange)}

/* logo upload */
/* drop target: the whole box takes a file, the label is the affordance */
.m-drop{position:relative;margin-top:8px}
.m-drop input[type=file]{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
/* This has to out-rank [data-bid-form] label, which comes later in the file
   and would otherwise flatten the drop face to display:block — the icon and
   the three lines then run together on one line. Same weight, later wins, so
   the form scope is named here rather than fought with !important. */
/* the label is a button in all but name: selecting its text only ever
   opened the file picker by accident */
[data-bid-form] .m-drop label{display:grid;justify-items:center;gap:2px;cursor:pointer;
  -webkit-user-select:none;user-select:none;
  margin:0;padding:22px 16px;border:1.5px dashed var(--line-strong);border-radius:var(--r-lg);
  background:var(--bg-alt);text-align:center;color:var(--ink);font-size:.95rem;font-weight:400;
  -webkit-font-smoothing:antialiased;transition:.16s var(--ease)}
[data-bid-form] .m-drop label:hover,[data-bid-form] .m-drop.is-over label{border-color:var(--orange);background:var(--orange-tint)}
[data-bid-form] .m-drop input:focus-visible + label{outline:2px solid var(--orange);outline-offset:2px}
.m-drop svg{width:24px;height:24px;color:var(--muted);margin-bottom:4px}
.m-drop b{font-size:.9rem;font-weight:600}
.m-drop span{font-size:.82rem;color:var(--muted)}
.m-drop i{font-style:normal;font-family:var(--mono-sm);font-size:10px;letter-spacing:.06em;
  color:var(--muted);margin-top:6px;-webkit-font-smoothing:none;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Once a file is chosen the box shows the artwork rather than describing it.
   The icon and the invitation give way to the thing itself. */
.m-file-thumb{display:none;max-width:100%;max-height:74px;width:auto;
  object-fit:contain;margin-bottom:8px}
.m-drop.has-file .m-file-thumb{display:block}
.m-drop.has-file svg{display:none}
.m-drop.has-file b{color:var(--orange-press);font-size:.82rem;font-weight:500}
.m-drop.has-file span{display:none}
.m-drop.too-big{--line-strong:#ca1c16}
.m-drop.too-big i{color:#ca1c16}
/* the one thing in the placement panel that is a decision rather than a dial */
.m-check{display:flex;align-items:flex-start;gap:10px;margin:4px 0 14px;
  padding:12px 14px;border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--bg-alt);cursor:pointer;text-transform:none;letter-spacing:0}
.m-check:hover{border-color:var(--line-strong)}
.m-check input{width:17px;height:17px;margin:2px 0 0;flex:none;accent-color:var(--orange)}
.m-check b{display:block;font-size:.88rem;font-weight:500;color:var(--ink)}
.m-check i{display:block;font-style:normal;font-size:.8rem;color:var(--muted);margin-top:2px}
.m-check:has(input:checked){border-color:var(--orange);background:var(--orange-tint)}


/* dialog layout: one column on a phone, form and preview side by side once
   there is room, so nothing has to be scrolled past to see the sticker */
[data-bid-form]{display:grid;gap:0}
.m-main{display:contents}
.m-side{margin-top:14px}

.m-stage{position:relative;display:block;width:100%;aspect-ratio:4/3;
  border-radius:var(--r-lg);overflow:hidden;background:var(--bg-alt);
  border:1px solid var(--line);margin:18px 0}
@media (min-width:1000px){.m-stage{display:none}}

/* stock picker */
.m-stocks{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:4px 0 6px}
/* Both cards stand the same height whatever their note says: the label is a
   grid so the box inside it fills the row. Qualified because the generic
   label rule further down would otherwise force it back to block. */
[data-bid-form] .m-stock{margin:0 !important;cursor:pointer;display:grid}
.m-stock input{position:absolute;opacity:0;width:1px;height:1px}
.m-stock span{display:block;border:1px solid var(--line-strong);border-radius:var(--r-lg);
  padding:9px 11px;background:var(--surface);transition:.15s var(--ease)}
/* what each stock actually looks like, so the choice is visible */
.swatch{display:block;height:34px;border-radius:var(--r-sm);margin-bottom:8px;
  border:1px solid rgba(28,23,21,.18);background-size:cover}
.swatch-border{background:#fff;box-shadow:inset 0 0 0 4px #fff,inset 0 0 0 5px rgba(28,23,21,.25)}
.swatch-clear{background:
  linear-gradient(135deg,rgba(255,255,255,.85),rgba(255,255,255,.05) 45%,rgba(255,255,255,.6)),
  repeating-conic-gradient(#e6e4e0 0% 25%,#f7f6f4 0% 50%) 0 0/12px 12px}
.m-stock b{display:block;font-size:.86rem;font-weight:600}
.m-stock i{display:block;font-style:normal;font-size:.74rem;color:var(--muted);margin-top:2px}
.m-stock input:checked + span{border-color:var(--orange);background:var(--orange-tint)}
.m-stock input:focus-visible + span{outline:2px solid var(--orange);outline-offset:2px}

/* the edge is its own choice, not a property of the stock */

/* step two: the card. The same panel as the placement controls, so the form
   does not change shape when it swaps step. */
.m-card{margin-top:14px;padding:var(--sp-4);border:1px solid var(--line);
  border-radius:var(--r-lg);background:var(--bg-alt)}
.m-card h4{margin:0 0 6px;font-size:1rem}
.m-card>p{margin:0 0 10px}
/* The deposit, set out rather than described: what it is a fifth of, then
   what leaves the card today. */
.m-sum{margin:12px 0 0;display:grid;gap:0;font-size:.9rem}
.m-sum > div{display:flex;justify-content:space-between;align-items:baseline;
  gap:16px;padding:9px 0;border-bottom:1px solid var(--line)}
.m-sum dt{color:var(--muted);margin:0}
.m-sum dd{margin:0;font-variant-numeric:tabular-nums;color:var(--ink)}
.m-sum .m-sum-due{border-bottom:0}
.m-sum .m-sum-due dt{color:var(--ink);font-weight:500}
.m-sum .m-sum-due dd{font-weight:600;font-size:1.05rem}
.m-card-mount{margin:14px 0 4px;min-height:44px}
/* the note under the button explains what was just pressed, so it needs air
   above it rather than sitting on the button's shoulder */
.m-card>p:last-child{margin:16px 0 0;line-height:1.6}

/* placement controls */
.m-place{margin-top:14px;padding:var(--sp-4);border:1px solid var(--line);
  border-radius:var(--r-lg);background:var(--bg-alt)}
.m-place p{margin:0 0 10px}
.m-place label{margin:12px 0 6px !important;font-size:.8rem !important}

/* The dials that place the sticker. Drawn rather than left to the platform:
   the default range control is a different object on every browser, and these
   sit in a panel with a stock picker and a checkbox that are all one design.
   A thin sunk track, a round handle that lifts under the finger, orange while
   it is being dragged. */
.m-place input[type=range]{width:100%;margin:0;background:none;cursor:pointer;
  -webkit-appearance:none;appearance:none;height:26px;accent-color:var(--orange)}
.m-place input[type=range]:focus{outline:none}
.m-place input[type=range]::-webkit-slider-runnable-track{
  height:4px;border-radius:99px;background:var(--line)}
.m-place input[type=range]::-moz-range-track{
  height:4px;border-radius:99px;background:var(--line)}
.m-place input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;
  width:18px;height:18px;margin-top:-7px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line-strong);
  box-shadow:0 1px 3px rgba(40,37,36,.18);
  transition:transform .12s var(--ease),border-color .12s var(--ease)}
.m-place input[type=range]::-moz-range-thumb{
  width:18px;height:18px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line-strong);
  box-shadow:0 1px 3px rgba(40,37,36,.18);
  transition:transform .12s var(--ease),border-color .12s var(--ease)}
.m-place input[type=range]:hover::-webkit-slider-thumb{border-color:var(--ink)}
.m-place input[type=range]:hover::-moz-range-thumb{border-color:var(--ink)}
.m-place input[type=range]:active::-webkit-slider-thumb,
.m-place input[type=range]:focus-visible::-webkit-slider-thumb{
  border-color:var(--orange);transform:scale(1.12)}
.m-place input[type=range]:active::-moz-range-thumb,
.m-place input[type=range]:focus-visible::-moz-range-thumb{
  border-color:var(--orange);transform:scale(1.12)}
.m-place input[type=range]:focus-visible{outline:2px solid var(--orange);
  outline-offset:4px;border-radius:99px}
@media (prefers-reduced-motion:reduce){
  .m-place input[type=range]::-webkit-slider-thumb{transition:none}
  .m-place input[type=range]::-moz-range-thumb{transition:none}
}
.m-place .btn{margin-top:12px}

/* the deposit note is a caveat on the button above it, not a caption glued
   to its edge */
.m-note{margin-top:12px}

/* something went wrong, said in the colour that means it, and sat directly
   above the button that will be pressed again */
.bid-err{color:var(--orange-press);font-weight:500;margin:14px 0 0}

/* modal */
/* The sheet holds its own scroll (see .modal-body), so the overlay behind it
   must not have one too, or there are two bars and two things to drag. */
.modal{position:fixed;inset:0;z-index:100;background:rgba(40,37,36,.5);
  display:flex;align-items:flex-end;justify-content:center;
  padding:0;overflow:hidden;overscroll-behavior:contain}
/* On a phone the bid is the whole task, so it gets the whole screen: a sheet
   that stops short leaves the page scrolling behind it and the form fighting
   for the last few hundred pixels. */
@media (max-width:999px){
  .modal{align-items:stretch;padding-top:10px}
  /* the whole screen, less the sliver of page left showing at the top: enough
     to read as a card laid over the page rather than a new one */
  .modal-card{max-width:none;min-height:calc(100svh - 10px);max-height:calc(100svh - 10px);
    border-radius:var(--r-xl) var(--r-xl) 0 0}
  .modal-x{top:10px;right:12px;padding:6px}
}
.modal-card{background:var(--surface);border-radius:var(--r-lg) var(--r-lg) 0 0;width:100%;
  max-width:min(560px,100vw);
  position:relative;border:1px solid var(--line);
  /* the form is taller than a laptop viewport once artwork is chosen */
  max-height:calc(100svh - clamp(24px,8vh,64px));display:flex;flex-direction:column}
.modal-scroll{overflow-y:auto;overscroll-behavior:contain}
/* The spot's name and size stay put; everything under them scrolls. A sheet
   that scrolls as a whole loses the one line telling you which spot you are
   bidding on the moment you reach for the form. */
/* The padding is on the pieces, not on the box, so the scrolling area runs
   the full width of the card and its scrollbar sits against the card's own
   edge rather than floating in the margin. */
.modal-inner{display:flex;flex-direction:column;min-height:0;
  --sheet-pad:clamp(20px,3vw,34px);
  padding:var(--sheet-pad) 0 0;overscroll-behavior:contain}
.modal-inner > h3,.modal-inner > .sub{flex:none;padding:0 var(--sheet-pad)}
.modal-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:0 var(--sheet-pad) var(--sheet-pad);scrollbar-gutter:stable;
  /* the platform's own scrolling: momentum on a phone, and the bar it draws
     for every other list on that device */
  -webkit-overflow-scrolling:touch}
.modal-x{position:absolute;top:14px;right:16px;border:0;background:none;font-size:1.5rem;
  cursor:pointer;color:var(--muted);line-height:1;border-radius:var(--r-sm)}
.modal-x:hover{color:var(--ink)}
/* the two price rows read as one block, so the air goes around the block
   rather than between its rows */
.m-row{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding:13px 0;border-bottom:1px solid var(--line);font-size:.94rem}
.m-row:first-of-type{margin-top:18px}
.m-row + .m-row{border-bottom:0}
[data-bid-form] label{display:block;font-family:var(--sans);font-size:.86rem;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--ink-2);margin:18px 0 7px;
  -webkit-font-smoothing:antialiased}
[data-bid-form] label .muted{font-weight:400}
.modal-card h3{font-family:var(--display);font-size:1.3rem;margin:0 34px 6px 0}
.modal-inner > .sub{margin:0}
.m-row{font-family:var(--sans)}
[data-bid-form] input{width:100%;padding:10px var(--sp-4);border:1px solid var(--line-strong);
  border-radius:var(--r-lg);font-size:1rem;font-family:inherit;background:var(--surface);color:var(--ink)}
[data-bid-form] input::placeholder{color:#8f8a87}
.m-input{display:flex;align-items:center;gap:8px;border:1px solid var(--line-strong);
  border-radius:var(--r-lg);padding-left:14px;background:var(--surface)}
.m-input:focus-within{border-color:var(--orange)}
.m-input span{color:var(--muted)}
.m-input input{border:0 !important;padding-left:0 !important}
.m-input input:focus{outline:none}

@media (max-width:900px){
  .hero .wrap{max-width:100%}
  .hero-head{max-width:100%}
  .hero h1{white-space:normal;font-size:clamp(2rem,8.4vw,2.9rem);letter-spacing:-.04em}
  .tagline{font-size:1.02rem;margin-bottom:20px}
  .hero .lede{font-size:1rem}
  .raised{max-width:100%}
  .raised-pct{font-size:.86rem}
  .raised-foot{font-size:.82rem}
  .hero-stage{margin:20px auto 6px}
  /* the buttons keep their own width on a phone; a full-bleed bar reads as
     a form footer, not a pair of choices */
  .cta-row{padding:0 8px 32px}
  .lid-views{width:100%;justify-content:center}
  .hero-head .lid-views{width:auto}
  .hero-grid{grid-template-columns:1fr}
  /* the headline sits a touch above centre on a phone: less at the top,
     more at the bottom, and the centred column moves up by half the difference */
  .hero{padding-top:4px;padding-bottom:84px;min-height:calc(100svh - var(--nav-h))}
  .section{padding:60px 0}
  .person{grid-template-columns:1fr;gap:20px}
  .bag{padding:0 18px 22px}
  .bag-item{grid-template-columns:64px 1fr;gap:14px}
  .bag-item-price{grid-column:1 / -1;font-size:1.25rem}
  .bag-row,.bag-total{gap:12px}
}

/* ------------------------------------------------------------------
   Motion — Framework-style: modules assembling, panels sliding into
   slots, everything settling on one easing curve.
   ------------------------------------------------------------------ */
.mono,.badge,.tag,.card-dims,.lid-foot,.spot-id,.spot-bid{font-family:var(--mono)}

/* hero entrance — each block rises, one after another */
html.js [data-rise]{opacity:0;transform:translateY(20px);
  transition:opacity .7s var(--ease),transform .7s var(--ease),filter .7s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms)}
/* Only the machine sharpens as it arrives: blurring type is blurring the
   thing being read, and the raised line and the countdown are both mid-count
   while it happens. The lid is a photograph coming into focus, which is what
   the effect was for. */
html.js [data-lid-stage][data-rise]{filter:blur(6px)}
html.js .is-lit [data-rise]{opacity:1;transform:none;filter:none}

/* section reveal */
html.js [data-reveal]{opacity:0;transform:translateY(18px);
  transition:opacity .6s var(--ease),transform .6s var(--ease);
  transition-delay:calc(var(--i,0) * 55ms)}
html.js [data-reveal].in{opacity:1;transform:none}

/* lid: exploded modules snapping into the top cover */
html.js .lid .spot{opacity:0;
  transform:translate(var(--dx,0),var(--dy,0)) scale(.86);
  transition:opacity .5s var(--ease),transform .62s var(--ease),background .15s,border-color .15s;
  transition-delay:calc(120ms + var(--i,0) * 45ms)}
html.js .lid.assembled .spot{opacity:1;transform:none}
html.js .lid .logo-slot{opacity:0;transition:opacity .5s var(--ease) .72s}
html.js .lid.assembled .logo-slot{opacity:1}
.lid.assembled:hover .spot{transform:translate(calc(var(--dx,0) * .16),calc(var(--dy,0) * .16));transition-delay:0ms}
.lid.assembled .spot:hover{transform:translateY(-2px) scale(1.03);z-index:2}

/* The bar fills itself — scaleX, never width.
 *
 * It used to sit at scaleX(0) waiting for a class the runtime adds inside a
 * double rAF, so anything that delayed or broke that script left the bar
 * empty: a background tab throttling rAF, a slow first frame, an error
 * earlier in the file. An animation needs nothing to arrive, so the bar
 * always ends up where the number says it is. */
.bar-fill{width:var(--w);transform-origin:left center}
html.js .bar-fill{animation:bar-fill 1.1s var(--ease) .25s both}
@keyframes bar-fill{from{transform:scaleX(0)}to{transform:none}}
@media (prefers-reduced-motion:reduce){html.js .bar-fill{animation:none}}

/* bag rows click into their slot from the right, like expansion cards */
html.js .bag [data-slot]{opacity:0;transform:translateX(14px);
  transition:opacity .45s var(--ease),transform .45s var(--ease);
  transition-delay:calc(180ms + var(--i,0) * 40ms)}
html.js .bag.in [data-slot]{opacity:1;transform:none}

.card,.spot{transition:border-color .18s var(--ease),background .18s var(--ease),transform .18s var(--ease)}
.card:hover{border-color:var(--line-strong)}
.nav-bar{transition:box-shadow .3s var(--ease),background .3s var(--ease),
  border-color .3s var(--ease)}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important}
  [data-reveal],[data-rise],.lid .spot,.lid .logo-slot,.bag [data-slot]{
    opacity:1 !important;transform:none !important;filter:none !important}
  .bar-fill{transform:none !important}
}
.no-anim [data-rise],.no-anim [data-reveal],.no-anim .lid .spot,.no-anim .lid .logo-slot,.no-anim .bag [data-slot]{opacity:1;transform:none}
.no-anim .bar-fill{transform:none;animation:none}

/* ------------------------------------------------------------------
   Bidding beside the machine.

   Kept at the end deliberately: this has the same specificity as the
   base .modal rules, so it only wins by coming after them.
   ------------------------------------------------------------------ */
@media (min-width:1000px){
  /* A popup on the machine's own layer: it is absolutely placed inside the
     hero rather than fixed over the page, so it scrolls with the thing it is
     editing and never covers it. */
  /* Fixed, not absolute: the hero is taller than the viewport, so centring
     inside it puts half the popup above the fold. Fixed keeps it centred on
     what you can actually see while it still carries no backdrop and never
     covers the machine. */
  .modal{position:fixed;inset:0 auto 0 0;height:100svh;width:auto;
    background:none;pointer-events:none;
    align-items:center;justify-content:flex-start;padding:0 0 0 clamp(8px,3vw,40px)}
  .modal-card{position:relative;max-width:400px;margin:0;pointer-events:auto;
    border-radius:var(--r-lg);border:1px solid var(--line);
    max-height:min(82svh,720px)}
  .m-main{display:block}
}

/* marquee — frame.work's homepage announcements band: one line of intent
   scrolling forever on a grey strip, with the tool drawn in brand orange. */
/* the track inside is thousands of pixels wide, and this is what keeps it
   from being part of the page's own width */
.marquee{overflow:hidden;contain:paint;margin-top:clamp(48px,7vw,90px);
  background:var(--bg-lid);padding:clamp(10px,1.5vw,18px) 0}
.marquee-track{display:flex;width:max-content;animation:marquee 60s linear infinite;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent)}
/* inline, not flex: a flex row drops the whitespace between the words and the
   tool, and the line reads as one run-on word */
.mq-item{display:block;white-space:nowrap;padding-right:2.4em;
  /* the band is set in the headline's own pixel face, so it takes the same
     treatment: whole-pixel sizes stepped at the breakpoints rather than
     scaled continuously, no smoothing, and the wide monospaced spaces
     pulled back in */
  font-family:Cozette,var(--mono),monospace;font-weight:400;
  letter-spacing:-.03em;word-spacing:-.16em;
  -webkit-font-smoothing:none;font-smooth:never;
  font-size:20px;line-height:1.3;color:var(--ink)}
@media (min-width:560px){.mq-item{font-size:26px}}
@media (min-width:900px){.mq-item{font-size:33px}}
.mq-dot{color:var(--orange);margin:0 .42em}
.mq-item b{font-weight:700;font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.marquee:hover .marquee-track{animation-play-state:paused}
@media (prefers-reduced-motion:reduce){.marquee-track{animation:none}}

/* The pixel face is only right on a screen that can hide its pixels. On a 1x
   display Cozette's unsmoothed 13px grid is the actual grid, so the headline,
   the brand mark and the marquee band read as jagged rather than as a
   deliberate bitmap. Below 1.5 device pixels per CSS pixel they fall back to
   the display face the rest of the page's headings already use, with the
   smoothing and spacing that face expects and sizes that scale freely, since
   nothing here is pinned to a bitmap grid any more. */
@media (max-resolution:1.49dppx){
  .hero h1,.brand,.mq-item{
    font-family:var(--display);
    -webkit-font-smoothing:auto;font-smooth:auto;
    word-spacing:normal}
  .hero h1{font-weight:600;letter-spacing:-.035em;
    font-size:clamp(1.9rem,5vw,3.9rem)}
  .brand{font-weight:600;letter-spacing:-.02em;font-size:clamp(14px,1.4vw,19px)}
  .mq-item{font-weight:500;letter-spacing:-.02em;font-size:clamp(18px,2.4vw,32px)}
  /* The same goes for Gohu, the pixel mono on the flat auction board and
     every small accent: prices, badges, dims, the countdown, the table
     heads. Dropping it from the two tokens hands all of them to DM Mono at
     the sizes they already set, and the smoothing they switched off comes
     back on, since DM Mono is drawn to be smoothed. */
  :root{
    --mono:var(--font-mono),"DM Mono",ui-monospace,Menlo,monospace;
    --mono-sm:var(--font-mono),"DM Mono",ui-monospace,Menlo,monospace}
  .mono,.badge,.tag,.card-dims,.lid-foot,.spot-id,.spot-bid,.pill,
  .lid-view,.cur-btn,.table th,.nav-visits,.raised-foot b,[data-countdown],
  .step-count,.hist-shown,.hist-art-none,.legal .updated,.m-drop i{
    -webkit-font-smoothing:auto;font-smooth:auto}
}
