/* Generated by static_build.py from src/slab-builder.src.html.
   Edit the source, not this file. */

/* ---------- tokens ---------- */
:root{
  --ground:#E8EBF0; --surface:#FFFFFF; --surface-2:#F3F5F9;
  --ink:#11151B; --ink-2:#56606E; --ink-3:#88919F;
  --line:#CBD2DC; --line-2:#E3E8EF;
  --red:#C8102E; --blue:#0B3FA8; --blue-wash:#E6EDFB; --good:#0E7A4B;
  --shadow-lift:0 18px 44px -20px rgba(17,21,27,.40);
  --shadow-flat:0 1px 0 rgba(17,21,27,.05);
  --radius:6px;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ground:#0E1218; --surface:#161B23; --surface-2:#1C222C;
    --ink:#ECEFF4; --ink-2:#9CA6B5; --ink-3:#6C7686;
    --line:#2B323D; --line-2:#232933;
    --red:#FF4A63; --blue:#7DA4FF; --blue-wash:#17233A; --good:#3FBF86;
    --shadow-lift:0 18px 44px -20px rgba(0,0,0,.75);
    --shadow-flat:0 1px 0 rgba(0,0,0,.35);
  }
}
:root[data-theme="dark"]{
  --ground:#0E1218; --surface:#161B23; --surface-2:#1C222C;
  --ink:#ECEFF4; --ink-2:#9CA6B5; --ink-3:#6C7686;
  --line:#2B323D; --line-2:#232933;
  --red:#FF4A63; --blue:#7DA4FF; --blue-wash:#17233A; --good:#3FBF86;
  --shadow-lift:0 18px 44px -20px rgba(0,0,0,.75);
  --shadow-flat:0 1px 0 rgba(0,0,0,.35);
}

*{box-sizing:border-box}

/* The hidden attribute only works through the UA stylesheet's [hidden]{display:none},
   which ANY author display rule outranks. .group{display:grid} did exactly that, so
   sections set hidden stayed on the page at full height while element.hidden read
   true - which also meant a scripted check of .hidden reported success. The
   !important is the point of the rule: it has to beat whatever a component sets. */
[hidden]{display:none !important}
body{
  margin:0;background:var(--ground);color:var(--ink);
  font-family:"Chivo","Helvetica Neue",Helvetica,Arial,sans-serif;
  font-size:15px;line-height:1.55;-webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0;text-wrap:balance}
button,input,select{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:3px}
img{max-width:100%;display:block}
.wrap{max-width:1180px;margin:0 auto;padding-inline:20px}

/* ---------- top bar ---------- */
.topbar{
  position:sticky;top:env(safe-area-inset-top,0px);z-index:40;
  background:color-mix(in srgb,var(--surface) 88%,transparent);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--line);
}
.topbar-in{display:flex;align-items:center;gap:14px;padding-block:11px}
.mark{display:flex;align-items:center;gap:10px;margin-right:auto;min-width:0}
.mark b{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:19px;letter-spacing:.02em;line-height:1;white-space:nowrap}
.mark span{font-size:11px;color:var(--ink-3);white-space:nowrap}
@media (max-width:620px){.mark span{display:none}}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;overflow:hidden;background:var(--surface)}
.seg button{appearance:none;border:0;background:transparent;cursor:pointer;padding:6px 13px;font-size:13px;font-weight:600;color:var(--ink-2)}
.seg button[aria-pressed="true"]{background:var(--ink);color:var(--surface)}
.themebtn{appearance:none;border:1px solid var(--line);background:var(--surface);width:34px;height:34px;border-radius:999px;cursor:pointer;font-size:15px;line-height:1}

/* ---------- intro ---------- */
.intro{padding-block:32px 24px;display:grid;gap:11px;max-width:62ch}
.intro h1{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:clamp(33px,6vw,52px);line-height:.98}
.intro p{margin:0;color:var(--ink-2);font-size:16px}

/* ---------- workbench ---------- */
.workbench{padding-bottom:52px}
.panel{max-width:700px;margin:0 auto}
/* The preview sits in normal flow, full size, right where it's placed in the
   page (after Holofoil) by default. It only floats &mdash; small, fixed to a
   corner of the screen &mdash; while the shopper is inside the visual-design
   range (Card design through Holofoil), which now comes BEFORE the preview's
   own spot on the page, so they can still see the card update as they pick.
   That's why this uses position:fixed rather than sticky at every width, not
   just on phones: sticky can only hold an element in place once you've
   reached it in the normal flow, and can't show it earlier than that. Once
   the shopper scrolls past Holofoil the float clears (.docked comes off) and
   the full preview simply appears in its normal place a moment later. */
.stage-col{position:static;max-width:360px;margin:0 auto}
.stage-col.docked{
  position:fixed;top:auto;right:14px;
  bottom:calc(env(safe-area-inset-bottom,0px) + 20px);
  z-index:45;width:112px;max-width:112px;margin:0;padding:0;
  background:none;box-shadow:none;
}
.stage-col.docked .stage{gap:4px}
.stage-col.docked .slab{width:112px}
.stage-col.docked .label,
.stage-col.docked .stagebar,
.stage-col.docked .previewbar{display:none}
.stage-col.docked .stage-hint,.stage-col.docked .examplenote{display:none}
.stage-col.docked .face{padding:4px;box-shadow:0 3px 10px rgba(0,0,0,.3),0 0 0 1px rgba(17,21,27,.14)}
.dock-cap{display:none}
.stage-col.docked .dock-cap{
  display:block;margin:0;text-align:center;
  font-size:10.5px;font-weight:700;letter-spacing:.02em;
  color:var(--ink-2);text-shadow:0 1px 3px var(--ground),0 1px 3px var(--ground);
}
/* The fixed price bar (.mobar) only shows up on phones and owns the bottom
   edge there, so the floating preview needs extra clearance above it. */
@media (max-width:920px){
  .stage-col.docked{bottom:calc(env(safe-area-inset-bottom,0px) + 82px)}
}

/* ---------- the slab ---------- */
.stage{perspective:1500px;display:grid;justify-items:center;gap:12px}
.slab{
  --rx:0deg;--ry:0deg;--sheen:50%;--foilhue:0deg;
  width:min(100%,336px);position:relative;
  transform:rotateX(var(--rx)) rotateY(var(--ry));
  transform-style:preserve-3d;transition:transform .35s cubic-bezier(.22,.7,.3,1);
}
.slab.is-live{transition:transform .06s linear}
.flip{position:relative;transform-style:preserve-3d;transition:transform .72s cubic-bezier(.4,.05,.2,1)}
.flip.flipped{transform:rotateY(180deg)}
.face{
  border-radius:12px;padding:10px 10px 12px;
  background:linear-gradient(150deg,#FBFCFE 0%,#E7EAF0 42%,#F7F9FC 100%);
  box-shadow:var(--shadow-lift),0 0 0 1px rgba(17,21,27,.14) inset,0 0 0 1px rgba(255,255,255,.7);
  display:grid;grid-template-rows:auto 1fr;gap:8px;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
}
.face.back{position:absolute;inset:0;transform:rotateY(180deg)}
/* The grading plate. A heavy red frame, white inside, identity down the left
   in plain bold sans, grade and barcode right, gold foil seal at the foot.
   Nothing is condensed or styled - it is an office-printed label and looking
   like one is the point.

   EVERY DIMENSION HERE IS FIXED. The plate does not grow, the columns do not
   trade width, and the rows do not move: an order with a long name has to sit
   on the same plate as an order with a short one. The three strings that vary
   are fitted by font size in renderLabel instead. Sizes come from the shop's
   own photo, where the name is 20% of plate height and the body lines 11%. */
.label{
  background:#EDEEF0;border-radius:3px;padding:3px 4px 5px;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset;color:#000;
}
.label-plate{
  box-sizing:border-box;position:relative;
  background:#FFF;border:5px solid #E02B28;
  padding:4px 9px;height:76px;
  display:grid;grid-template-columns:1fr 98px;gap:8px;align-items:start;
}
/* Content box is 76 - 10 border - 8 padding = 58px. Both columns are cut to
   fit that exactly: 21+17+17 on the left, 15+20+23 on the right. */
.label-main{min-width:0;overflow:hidden;display:grid;grid-template-rows:21px 17px 17px;
  align-content:start}
.label-name{
  font:700 16px/21px "Helvetica Neue",Helvetica,Arial,sans-serif;
  letter-spacing:-.006em;white-space:nowrap;overflow:hidden;
}
.label-line{font:400 11px/17px "Helvetica Neue",Helvetica,Arial,sans-serif;
  white-space:nowrap;overflow:hidden}

/* The maker's mark: a small grey sticker reading "M6 Slabs", set on its own
   plate over the middle of the label's bottom rail, the way the shop's own
   printed labels carry it. */
.label-mark{
  position:absolute;left:50%;bottom:2px;transform:translateX(-50%);
  padding:2px 7px;border-radius:3px;
  background:#C9CBCF;color:#000;
  font:700 italic 10px/1.3 "Helvetica Neue",Helvetica,Arial,sans-serif;
  white-space:nowrap;
  box-shadow:0 0 0 .5px rgba(0,0,0,.15), 0 1px 1px rgba(0,0,0,.15);
}

.label-cert{display:grid;grid-template-rows:15px 20px 23px;justify-items:end;text-align:right;
  min-width:0;overflow:hidden}
.label-auth{font:700 11.5px/15px "Helvetica Neue",Helvetica,Arial,sans-serif;white-space:nowrap}
.label-grade{font:700 16px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;white-space:nowrap}
/* First and last digit flank the bars, the two blocks of five sit under them. */
.label-code{display:grid;grid-template-columns:auto 1fr auto;gap:2px;align-items:end}
.label-barcode{display:block;height:16px;width:84px}
.label-barnum{display:flex;justify-content:space-between;padding:0 2px}
.label-digit,.label-barnum{
  font:400 6.5px/1.1 "Helvetica Neue",Helvetica,Arial,sans-serif;
  letter-spacing:.02em;font-variant-numeric:tabular-nums;color:#000;
}
.label-digit{padding-bottom:1px}
.label.is-back .label-name{font-size:12px;color:#5A6472}

.window{position:relative;aspect-ratio:2.5/3.5;border-radius:4px;overflow:hidden;background:#0A0C10;box-shadow:0 0 0 1px rgba(17,21,27,.22)}
.window img,.window canvas{width:100%;height:100%;object-fit:cover;display:block}
.window .missing{
  position:absolute;inset:0;display:grid;place-content:center;gap:6px;text-align:center;
  background:repeating-linear-gradient(45deg,#1A1F28 0 10px,#151A22 10px 20px);
  color:#8A93A1;font-size:12px;padding:20px;
}
.window .missing b{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:15px;color:#C3CAD6}

/* Live option swatches. The shop's own border and background artwork, recoloured
   per pixel on a canvas — see recolour() in the script. */
.tile{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius);padding:9px}

/* ---------- photo ---------- */
.dropzone{
  border:1.5px dashed var(--line);border-radius:var(--radius);background:var(--surface);
  padding:18px 16px;display:grid;gap:7px;justify-items:center;text-align:center;cursor:pointer;
  transition:border-color .15s ease, background .15s ease;
}
.dropzone:hover,.dropzone.over{border-color:var(--ink);background:var(--surface-2)}
.dropzone b{font-size:13.5px}
.dropzone span{font-size:11.5px;color:var(--ink-3)}
.dropzone input[type="file"]{position:absolute;width:1px;height:1px;opacity:0}

.photolist{display:grid;gap:8px}
.photorow{
  display:grid;grid-template-columns:auto 1fr auto;gap:11px;align-items:center;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:9px 11px;
}
.photorow .thumb{
  width:46px;height:64px;border-radius:3px;object-fit:cover;background:#0A0C10;flex:none;
  border:1px solid var(--line-2);
}
.photorow .meta{display:grid;gap:4px;min-width:0}
.photorow .fname{font-size:13px;font-weight:600;overflow-wrap:anywhere}
.photorow .dims{font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.photorow input.who{
  width:100%;padding:6px 9px;border:1px solid var(--line);border-radius:4px;
  background:var(--surface-2);font-size:12.5px;
}
.photorow .drop{
  appearance:none;border:1px solid var(--line);background:transparent;color:var(--ink-3);
  width:28px;height:28px;border-radius:999px;cursor:pointer;font-size:15px;line-height:1;flex:none;
}
.photorow .drop:hover{border-color:var(--red);color:var(--red)}

.verdict{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;border-radius:999px;padding:1px 8px}
.verdict::before{content:"";width:6px;height:6px;border-radius:999px;background:currentColor}
.verdict.good{color:var(--good);background:color-mix(in srgb,var(--good) 14%,transparent)}
.verdict.ok{color:#9A6B00;background:rgba(245,166,35,.16)}
.verdict.bad{color:var(--red);background:color-mix(in srgb,var(--red) 14%,transparent)}
:root[data-theme="dark"] .verdict.ok{color:#F5C46B}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .verdict.ok{color:#F5C46B}}

/* ---------- roster ---------- */
.roster{display:grid;gap:8px}
.rrow{
  display:grid;grid-template-columns:22px 52px minmax(0,1fr);gap:11px;align-items:start;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:9px 11px;
}
.rrow.needs{border-color:color-mix(in srgb,var(--red) 45%,var(--line))}
.rnum{font-size:12px;font-weight:700;color:var(--ink-3);text-align:right;padding-top:9px;font-variant-numeric:tabular-nums}
.rphoto{
  position:relative;width:52px;height:72px;border-radius:4px;overflow:hidden;cursor:pointer;
  border:1px dashed var(--line);display:grid;place-items:center;background:var(--surface-2);
}
.rphoto:hover{border-color:var(--ink)}
.rphoto img{width:100%;height:100%;object-fit:cover}
.rphoto span{font-size:9px;color:var(--ink-3);text-align:center;line-height:1.2;padding:0 3px}
.rphoto input{position:absolute;inset:0;opacity:0;cursor:pointer}
.rfields{display:grid;grid-template-columns:minmax(0,2fr) 68px minmax(0,1.4fr);gap:7px}
.rfields .bio{grid-column:1/-1}
.rfields input,.rfields select{
  width:100%;padding:7px 9px;border:1px solid var(--line);border-radius:4px;
  background:var(--surface-2);font-size:12.5px;
}
.rfields input::placeholder{color:var(--ink-3)}
@media (max-width:560px){.rfields{grid-template-columns:minmax(0,1fr) 64px}.rfields select{grid-column:1/-1}}
.rrow .dpi{grid-column:3;font-size:10.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}

textarea#f-notes{
  width:100%;padding:10px 11px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);font-family:inherit;font-size:13.5px;resize:vertical;min-height:74px;
}

.previewbar{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap}
.previewbar button{
  appearance:none;border:1px solid var(--line);background:var(--surface);border-radius:999px;
  width:26px;height:26px;cursor:pointer;font-size:14px;line-height:1;color:var(--ink-2);
}
.previewbar button:disabled{opacity:.35;cursor:not-allowed}
.previewbar span{font-size:11.5px;color:var(--ink-2);font-variant-numeric:tabular-nums}

.photonote{margin:0;font-size:11.5px;color:var(--ink-3)}
.photonote.warn{color:var(--red)}

/* Real holofoil, lifted from the shop's own stock — see foils.py. The alpha
   channel IS the effect: the card shows through wherever the sheet is flat, so
   only the flecks and the sheen sit on top.

   screen, not color-dodge: dodge drove the highlights to pure white and ate the
   artwork underneath. The sheet itself never moves — it is laminated to the card.
   Two things answer the pointer: the slab turns, and the foil's lit band and hue
   travel across it. Nothing paints a highlight over the artwork any more, so the
   only light that moves is the light on the flecks. */
.foil{
  position:absolute;inset:0;pointer-events:none;z-index:5;
  background-repeat:no-repeat;
  background-position:center;          /* the pattern is laminated on, it never slides */

  /* The light is what moves. This mask is a band of full opacity with steep
     falloff either side; sliding it lets one strip of foil blaze while the rest
     drops back, which is the single thing that stops it reading as print. */
  -webkit-mask-image:linear-gradient(100deg,
     rgba(0,0,0,.16) 26%, rgba(0,0,0,.72) 39%, #000 48%,
     #000 54%, rgba(0,0,0,.72) 63%, rgba(0,0,0,.16) 76%);
          mask-image:linear-gradient(100deg,
     rgba(0,0,0,.16) 26%, rgba(0,0,0,.72) 39%, #000 48%,
     #000 54%, rgba(0,0,0,.72) 63%, rgba(0,0,0,.16) 76%);
  -webkit-mask-size:230% 100%;  mask-size:230% 100%;
  -webkit-mask-position:var(--sheen, 50%) 0;  mask-position:var(--sheen, 50%) 0;

  /* and the colour swings with the angle — holographic film splits the spectrum
     differently at every tilt, which no static texture can imply */
  filter:hue-rotate(var(--foilhue, 0deg)) saturate(1.35) contrast(1.18);
  transition:filter .12s linear;
}
/* Wave has no transparent ground, so the contrast boost that makes shard and
   star's flecks pop just pales the whole card. It gets saturation only. */
.foil[data-foil="wave"]{filter:hue-rotate(var(--foilhue, 0deg)) saturate(1.3)}
.slab.is-live .foil{transition:none}

/* `screen` can only add light, so on a white card the foil was invisible by
   construction. This multiply pass darkens where the flecks are, which is what
   makes them read on pale artwork; on dark artwork it barely registers because
   the card is already dark. Same texture, same band, one layer below. */
/* Opacity is set per card by renderSlab, from the card's own measured
   lightness. On dark artwork this pass has nothing to add and its flecks read
   as black blobs, so there it is simply off. */
.foilshade{
  position:absolute;inset:0;pointer-events:none;z-index:4;
  mix-blend-mode:multiply;opacity:var(--shadeop, 0);
  background-repeat:no-repeat;background-position:center;
  -webkit-mask-image:linear-gradient(100deg,
     rgba(0,0,0,.16) 26%, rgba(0,0,0,.72) 39%, #000 48%,
     #000 54%, rgba(0,0,0,.72) 63%, rgba(0,0,0,.16) 76%);
          mask-image:linear-gradient(100deg,
     rgba(0,0,0,.16) 26%, rgba(0,0,0,.72) 39%, #000 48%,
     #000 54%, rgba(0,0,0,.72) 63%, rgba(0,0,0,.16) 76%);
  -webkit-mask-size:230% 100%;mask-size:230% 100%;
  -webkit-mask-position:var(--sheen, 50%) 0;mask-position:var(--sheen, 50%) 0;
  filter:hue-rotate(var(--foilhue, 0deg)) saturate(1.2);
  /* matched to .foil, or the multiply and screen halves of one foil drift apart
     in colour for .12s every time the pointer leaves */
  transition:filter .12s linear;
}
.slab.is-live .foilshade{transition:none}
.foilshade[data-foil="none"]{display:none}
.foilshade[data-foil="shard"]{background-image:var(--foil-shard);background-size:165% auto}
.foilshade[data-foil="star"]{background-image:var(--foil-star);background-size:145% auto}
.foilshade[data-foil="wave"]{
  opacity:calc(var(--shadeop, 0) * .6);
  -webkit-mask-image:linear-gradient(100deg,
     rgba(0,0,0,.55) 22%, rgba(0,0,0,.798) 40%, #000 50%,
     rgba(0,0,0,.798) 60%, rgba(0,0,0,.55) 78%);
          mask-image:linear-gradient(100deg,
     rgba(0,0,0,.55) 22%, rgba(0,0,0,.798) 40%, #000 50%,
     rgba(0,0,0,.798) 60%, rgba(0,0,0,.55) 78%);
  background-image:var(--foil-wave);background-size:190% auto;opacity:.26;
}

.foil[data-foil="none"]{display:none}
/* screen for the particle foils: flecks ADD light, and where the sheet is flat
   the alpha is zero so nothing happens. */
.foil[data-foil="shard"]{
  mix-blend-mode:screen;
  opacity:.82;background-image:var(--foil-shard);
  background-size:165% auto;background-position:center;
}
.foil[data-foil="star"]{
  mix-blend-mode:screen;
  opacity:.92;background-image:var(--foil-star);
  background-size:145% auto;background-position:center;
}
/* Wave is a full-coverage sheen rather than particles, so screen lifts every
   black on the card and fogs it — tested on Edge and Playing Card and it ruined
   both. overlay keeps the blacks black and the reds saturated while still
   showing the pastel shift. */
/* Shallow band for wave only — see the note above: with a textureless sheet a
   steep band has nothing to break it up and reads as a bar of glare. */
.foil[data-foil="wave"]{
  -webkit-mask-image:linear-gradient(100deg,
     rgba(0,0,0,.55) 22%, rgba(0,0,0,.798) 40%, #000 50%,
     rgba(0,0,0,.798) 60%, rgba(0,0,0,.55) 78%);
          mask-image:linear-gradient(100deg,
     rgba(0,0,0,.55) 22%, rgba(0,0,0,.798) 40%, #000 50%,
     rgba(0,0,0,.798) 60%, rgba(0,0,0,.55) 78%);
  mix-blend-mode:overlay;
  opacity:.34;background-image:var(--foil-wave);
  background-size:190% auto;background-position:center;
}

.stagebar{display:flex;align-items:center;justify-content:center;gap:9px;flex-wrap:wrap}
.flipbtn{appearance:none;cursor:pointer;border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:6px 14px;font-size:12.5px;font-weight:700;color:var(--ink-2)}
.flipbtn:hover:not(:disabled){border-color:var(--ink);color:var(--ink)}
.flipbtn:disabled{opacity:.42;cursor:not-allowed}
.stage-hint{font-size:11.5px;color:var(--ink-3);text-align:center;max-width:36ch;margin:0}

/* ---------- options ---------- */
.panel{display:grid;gap:14px}

/* Each decision gets its own surface. As a flat stack separated only by a gap
   it read as one long form; as cards it reads as a set of choices, which is
   what it is. */
.group{
  display:grid;gap:10px;
  background:var(--surface);
  border:1px solid var(--line-2);
  border-radius:var(--radius);
  padding:13px 15px 15px;
  box-shadow:var(--shadow-flat);
}

/* Outstanding work, on the one section that can have any. Sections that cannot
   be incomplete get no badge - a light that is always green is not a light. */
.gtodo{
  margin-left:auto;font-size:10.5px;font-weight:700;letter-spacing:.01em;
  padding:2px 8px;border-radius:999px;white-space:nowrap;
  background:var(--blue-wash);color:var(--blue);
}
.gtodo[data-done="1"]{background:transparent;color:var(--good);padding-left:0}

/* Order type. Two real alternatives, so a segmented pair rather than a dropdown:
   both options and their consequences are visible without opening anything. */
.modebar{position:relative;display:flex;border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--surface-2)}
.modebar input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.modebar label{
  flex:1 1 0;display:grid;gap:3px;padding:11px 13px;cursor:pointer;
  border-right:1px solid var(--line);
  transition:background .12s linear;
}
.modebar label:last-child{border-right:0}
.modebar label:hover{background:var(--surface)}
.modebar strong{font-size:13px;font-weight:700;color:var(--ink-2)}
.modebar span{font-size:11px;color:var(--ink-3);line-height:1.35}
.modebar input:checked + label{background:var(--surface)}
.modebar input:checked + label strong{color:var(--red)}
.modebar input:focus-visible + label{outline:2px solid var(--blue);outline-offset:-2px}
@media (max-width:420px){.modebar{flex-direction:column}
  .modebar label{border-right:0;border-bottom:1px solid var(--line)}
  .modebar label:last-child{border-bottom:0}}
.group > h2{font-size:12.5px;font-weight:700;color:var(--ink-2);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.group > h2 em{font-style:normal;font-weight:400;color:var(--ink-3);font-size:12px}
.group.muted{opacity:.55}
.scopenote{margin:0;font-size:11.5px;color:var(--ink-3)}
/* Both of these are written by renderSlab and neither had a rule anywhere, so
   the example badge and its caption rendered as bare unstyled text. */
.exchip{
  position:absolute;left:8px;top:8px;z-index:7;
  font:700 8px/1 "Helvetica Neue",Helvetica,Arial,sans-serif;letter-spacing:.09em;
  text-transform:uppercase;padding:4px 7px;border-radius:3px;
  background:rgba(17,21,27,.74);color:#fff;pointer-events:none;
}
.examplenote{display:none}

.styles{display:grid;grid-template-columns:repeat(4,1fr);gap:9px}
@media (max-width:560px){.styles{grid-template-columns:repeat(2,1fr)}}
.swatch{position:relative}
.swatch input{position:absolute;opacity:0;width:1px;height:1px}
.swatch label{display:grid;gap:6px;cursor:pointer;border-radius:var(--radius);padding:6px;border:1px solid var(--line);background:var(--surface)}
.swatch .mini{position:relative;aspect-ratio:2.5/3.5;border-radius:3px;overflow:hidden;background:#0A0C10}
.swatch .mini img{width:100%;height:100%;object-fit:cover}
.swatch .nmlabel{font-size:11.5px;font-weight:700;text-align:center;color:var(--ink-2);line-height:1.25}
.swatch .nmlabel .tag{display:inline-block;margin-top:2px;color:var(--red);font-weight:800;letter-spacing:.01em}
.swatch input:checked + label{border-color:var(--ink);box-shadow:0 0 0 2px var(--ink)}
.swatch input:checked + label .nmlabel{color:var(--ink)}
.swatch input:focus-visible + label{outline:2px solid var(--blue);outline-offset:2px}
.swatch input:disabled + label{cursor:not-allowed}

.pills{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.pills .swatch label{display:flex;align-items:center;gap:9px;padding:6px 13px 6px 7px;border-radius:999px}
.pills .chip{width:22px;height:22px;border-radius:999px;border:1px solid rgba(17,21,27,.2);flex:none}
.pills .sq{border-radius:5px}
.pills img.chip{object-fit:cover}
.pills .swatch label > span:last-child{font-size:13px;font-weight:600}
.chip-none{background:repeating-linear-gradient(45deg,#D5DAE2 0 4px,#EDF0F4 4px 8px)}
/* the swatches are the same scanned stock, over a dark base so the alpha reads */
.chip-wave,.chip-shard,.chip-star{background-color:#171d28;background-size:cover;background-position:center}
.chip-wave{background-image:var(--foil-wave)}
.chip-shard{background-image:var(--foil-shard)}
.chip-star{background-image:var(--foil-star)}
.chip-steel{background:linear-gradient(120deg,#EDF0F4,#A9B2BE 42%,#F5F7FA 62%,#95A0AE)}
.chip-coloured{background:conic-gradient(#E53935,#FB8C00,#FDD835,#43A047,#1E88E5,#8E24AA,#E53935)}
.chip-smoke{background:radial-gradient(70% 70% at 30% 35%,#C77 0%,#4A2340 55%,#120A12 100%)}
.chip-lasers{background:repeating-linear-gradient(48deg,#12081C 0 4px,#7B2BD6 4px 5px,#12081C 5px 9px,#2ED0FF 9px 10px)}
.chip-flame{background:linear-gradient(0deg,#FFD24A 0%,#F5761A 42%,#B3221A 74%,#2A0A08 100%)}


/* The colour sits at the end of the row of finishes it applies to, because the
   pills already show the colour on their own chips - the swatch is the control,
   not another preview. */
.pillrow{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.cswatch{
  display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  border:1px solid var(--line);border-radius:999px;padding:2px 8px 2px 3px;
  background:var(--surface-2);
}
.cswatch:hover{border-color:var(--ink-3)}
/* focus-within, not :focus - focus lands on the input inside the label. */
.cswatch:focus-within{outline:2px solid var(--blue);outline-offset:2px}
.cswatch input[type="color"]{
  appearance:none;-webkit-appearance:none;border:0;background:transparent;padding:0;
  cursor:pointer;width:19px;height:19px;border-radius:999px;overflow:hidden;flex:none;
}
.cswatch input[type="color"]::-webkit-color-swatch-wrapper{padding:0}
.cswatch input[type="color"]::-webkit-color-swatch{border:1px solid rgba(17,21,27,.2);border-radius:999px}
.cswatch code{font-size:11px;color:var(--ink-2);font-variant-numeric:tabular-nums}


.colourpick{display:flex;align-items:center;gap:8px;border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:4px 12px 4px 5px}
.colourpick input[type="color"]{
  appearance:none;border:0;background:transparent;padding:0;cursor:pointer;
  width:26px;height:26px;border-radius:999px;overflow:hidden;flex:none;
}
.colourpick input[type="color"]::-webkit-color-swatch-wrapper{padding:0}
.colourpick input[type="color"]::-webkit-color-swatch{border:1px solid rgba(17,21,27,.2);border-radius:999px}
.colourpick label{font-size:12.5px;font-weight:600;color:var(--ink-2);white-space:nowrap}
.colourpick code{font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}

.fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
@media (max-width:560px){.fields{grid-template-columns:1fr}}
.field{display:grid;gap:5px}
.field label{font-size:12px;font-weight:600;color:var(--ink-2)}
.field input,.field select,.field textarea{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);font:inherit}
.field textarea{resize:vertical;min-height:90px}

.counts{display:grid;gap:8px}
.count{display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:10px 12px}
.count .t{font-size:13.5px;font-weight:600}
.count .s{font-size:12px;color:var(--ink-3)}
.stepper{display:flex;align-items:center;gap:2px;border:1px solid var(--line);border-radius:999px;padding:2px;background:var(--surface-2)}
.stepper button{appearance:none;border:0;background:transparent;cursor:pointer;width:30px;height:30px;border-radius:999px;font-size:17px;line-height:1;color:var(--ink-2)}
.stepper button:hover{background:var(--surface);color:var(--ink)}
.stepper input{width:46px;text-align:center;border:0;background:transparent;font-weight:700;font-variant-numeric:tabular-nums;-moz-appearance:textfield}
.stepper input::-webkit-outer-spin-button,.stepper input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* ---------- ledger ---------- */
.ledger{background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow-flat);overflow:hidden}
.ledger h2{padding:12px 16px;font-size:13px;font-weight:700;border-bottom:1px solid var(--line-2)}
.spec{padding:11px 16px;border-bottom:1px solid var(--line-2);background:var(--surface-2);display:grid;gap:4px}
.spec div{display:grid;grid-template-columns:82px 1fr;gap:10px;font-size:12.5px}
.spec dt{color:var(--ink-3);font-weight:600}
.spec dd{margin:0;font-weight:600;display:flex;align-items:center;gap:6px}
.spec .dot{width:11px;height:11px;border-radius:3px;border:1px solid rgba(17,21,27,.25);flex:none}
.lines{padding:5px 16px 11px;display:grid}
.line{display:grid;grid-template-columns:1fr auto;gap:12px;padding:7px 0;align-items:baseline}
.line .lbl{font-size:13.5px}
.line .sub{display:block;font-size:11.5px;color:var(--ink-3)}
.line .amt{font-variant-numeric:tabular-nums;font-weight:600;font-size:13.5px}
.line.free .amt{color:var(--good)}
.line.rule{border-top:1px solid var(--line-2);margin-top:5px;padding-top:11px}
.tierchip{display:inline-block;margin-left:6px;font-size:10.5px;font-weight:700;background:var(--blue-wash);color:var(--blue);padding:1px 6px;border-radius:999px;vertical-align:1px}
.total{display:grid;grid-template-columns:1fr auto;align-items:center;gap:12px;padding:13px 16px;background:var(--ink);color:var(--ground)}
.total .cap{font-size:12px;font-weight:600;opacity:.75}
.total .big{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:31px;line-height:1;font-variant-numeric:tabular-nums}
.nudge{margin:0;padding:11px 16px;border-top:1px solid var(--line-2);background:var(--surface-2);font-size:12.5px;color:var(--ink-2)}
.nudge b{color:var(--ink)}
.discount{padding:0 16px 12px;display:grid;gap:8px}
.discount-row{display:flex;gap:8px}
.discount-row input{
  flex:1;min-width:0;border:1px solid var(--line);border-radius:8px;
  padding:9px 11px;font:inherit;font-size:13px;background:var(--surface);color:var(--ink);
  text-transform:uppercase;letter-spacing:.02em;
}
.discount-row input::placeholder{text-transform:none;letter-spacing:0;color:var(--ink-3)}
.discount-row .btn{padding:9px 16px;font-size:12.5px}
.discount-applied{display:flex;flex-wrap:wrap;gap:6px}
.discount-applied:empty{display:none}
.code-chip{
  display:inline-flex;align-items:center;gap:6px;
  background:color-mix(in srgb,var(--good) 14%,transparent);color:var(--good);
  font-size:11.5px;font-weight:700;padding:4px 6px 4px 10px;border-radius:999px;
}
.code-chip button{
  appearance:none;border:none;background:none;color:inherit;cursor:pointer;
  font-size:15px;line-height:1;padding:0 2px;opacity:.7;
}
.code-chip button:hover{opacity:1}
.discount-msg{margin:0;font-size:11.5px;color:var(--ink-3)}
.discount-msg.warn{color:var(--red)}
.actions{display:flex;flex-wrap:wrap;gap:9px;padding:12px 16px;border-top:1px solid var(--line-2)}
.btn{appearance:none;cursor:pointer;border-radius:999px;padding:10px 18px;font-size:13.5px;font-weight:700;border:1px solid var(--ink);background:var(--ink);color:var(--surface)}
.btn.ghost{background:transparent;color:var(--ink)}
.btn:disabled{opacity:.45;cursor:not-allowed}

/* ---------- bands ---------- */
.band{border-top:1px solid var(--line);background:var(--surface)}
.band.alt{background:var(--ground)}
.band-in{padding-block:44px}
h2.sec{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:clamp(23px,3.6vw,33px);line-height:1.05}
p.sec{margin:8px 0 24px;color:var(--ink-2);max-width:62ch}

.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
@media (max-width:860px){.gallery{grid-template-columns:repeat(2,1fr)}}
.gitem{display:grid;gap:9px;align-content:start;cursor:pointer;border-radius:8px;
  padding:6px;margin:-6px;transition:background .15s ease}
.gitem:hover{background:var(--surface-2)}
.gitem:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.gpair{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.gpair figure{margin:0;display:grid;gap:4px}
.gpair .shot{aspect-ratio:2.5/3.5;border-radius:4px;overflow:hidden;background:#0A0C10;box-shadow:var(--shadow-lift)}
.gpair .shot img{width:100%;height:100%;object-fit:cover}
.gpair figcaption{font-size:10.5px;font-weight:700;color:var(--ink-3);text-align:center}
.gpair .none{aspect-ratio:2.5/3.5;border-radius:4px;border:1px dashed var(--line);display:grid;place-content:center;text-align:center;padding:10px;font-size:10.5px;color:var(--ink-3)}
.gitem h3{font-size:14.5px;font-weight:700;display:flex;align-items:center;gap:7px}
.gitem h3 i{width:9px;height:9px;border-radius:2px;flex:none;font-style:normal}
.gitem p{margin:0;font-size:12.5px;color:var(--ink-2)}
.gitem p.madeup{font-size:11.5px;color:var(--ink-3)}
.gitem .load{justify-self:start;appearance:none;border:1px solid var(--line);background:transparent;border-radius:999px;padding:5px 12px;font-size:12px;font-weight:700;cursor:pointer;color:var(--ink-2)}
.gitem .load:hover{border-color:var(--ink);color:var(--ink)}

.split{display:grid;grid-template-columns:minmax(0,330px) minmax(0,1fr);gap:34px;align-items:start}
@media (max-width:820px){.split{grid-template-columns:1fr;gap:22px}}
.shotframe{border-radius:8px;overflow:hidden;box-shadow:var(--shadow-lift);background:var(--surface)}
.optnotes{display:grid;gap:15px}
.optnote{display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start}
.optnote .chip{width:30px;height:30px;border-radius:6px;border:1px solid rgba(17,21,27,.2);flex:none;margin-top:2px}
.optnote b{font-size:13.5px}
.optnote span{display:block;font-size:12.5px;color:var(--ink-2)}
.caveat{margin:18px 0 0;font-size:12px;color:var(--ink-3);border-left:2px solid var(--line);padding-left:12px;max-width:62ch}

.rates{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:18px}
.rate{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--surface)}
.rate h3{padding:11px 14px;font-size:13px;font-weight:700;border-bottom:1px solid var(--line-2);background:var(--surface-2)}
table{width:100%;border-collapse:collapse;font-size:13.5px}
th,td{text-align:left;padding:8px 14px;border-bottom:1px solid var(--line-2)}
tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
thead th{font-size:11.5px;color:var(--ink-3);font-weight:700}
.tablewrap{overflow-x:auto}
.rate.wide{grid-column:span 2}
@media (max-width:820px){.rate.wide{grid-column:span 1}}
tbody tr.here{background:var(--blue-wash)}
tbody tr.here td{font-weight:700;color:var(--blue)}
.ratenote{margin:0;padding:10px 14px;font-size:12px;color:var(--ink-3);border-top:1px solid var(--line-2)}

.notes{border-top:1px solid var(--line);background:var(--ground)}
.notes-in{padding-block:38px 52px;display:grid;gap:20px}
.notes h2{font-size:14px;font-weight:700}
.notelist{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:20px;margin:0;padding:0;list-style:none}
.notelist li{display:grid;gap:4px;border-left:2px solid var(--red);padding-left:12px}
.notelist b{font-size:13.5px}
.notelist span{font-size:13px;color:var(--ink-2)}
.fineprint{font-size:12px;color:var(--ink-3);max-width:76ch;margin:0}

.mobar{display:none}
@media (max-width:920px){
  .mobar{
    display:grid;grid-template-columns:1fr auto;align-items:center;gap:12px;
    position:fixed;left:0;right:0;bottom:0;z-index:50;background:var(--ink);color:var(--ground);
    padding:10px 18px calc(10px + env(safe-area-inset-bottom,0px));
  }
  .mobar .cap{font-size:11.5px;opacity:.75}
  .mobar .big{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:24px;line-height:1;font-variant-numeric:tabular-nums}
  .mobar .btn{background:var(--ground);color:var(--ink);border-color:var(--ground);padding:9px 15px;font-size:12.5px}
  body{padding-bottom:72px}
}
@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms !important;transition-duration:.01ms !important}}

/* ---------- foil preview loop ---------- */
.foilpreview{
  display:grid;gap:6px;justify-items:start;
}
.foilpreview .fp-frame{
  width:112px;border-radius:8px;overflow:hidden;border:1px solid var(--line);
  background:#000;box-shadow:var(--shadow-flat);aspect-ratio:9/16;
}
.foilpreview .fp-frame video{width:100%;height:100%;object-fit:cover;display:block}
.foilpreview .fp-cap{font-size:11px;color:var(--ink-3);max-width:130px;line-height:1.4}
@media (max-width:480px){.foilpreview .fp-frame{width:92px}}

/* ---------- shared page nav (multi-page site) ---------- */
.navlink{white-space:nowrap;font-size:13px;font-weight:700;color:var(--ink);text-decoration:none;border:1px solid var(--line);border-radius:999px;padding:6px 13px;background:var(--surface)}
.navlink[aria-current]{background:var(--ink);color:var(--surface)}
.navs{display:flex;gap:6px}
@media (max-width:620px){
  .topbar-in{flex-wrap:wrap;row-gap:8px}
  .navs{order:3;width:100%;overflow-x:auto;padding-bottom:2px}
  .mark{margin-right:auto}
}

/* ---------- about page ---------- */
.about-photo{border-radius:10px;overflow:hidden;box-shadow:var(--shadow-lift);background:var(--surface)}
.about-photo img{width:100%;height:auto;display:block;aspect-ratio:4/5;object-fit:cover;object-position:50% 15%}
.about-quote{
  margin:0;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2);
  padding:14px 16px;font-size:13.5px;font-style:italic;color:var(--ink-2);line-height:1.55;
}
.about-quote footer{margin-top:8px;font-style:normal;font-size:12px;color:var(--ink-3)}
.about-stats{display:flex;gap:18px;flex-wrap:wrap;margin:2px 0 0}
.about-stats div{display:grid;gap:1px}
.about-stats b{font-family:Anton,Impact,sans-serif;font-weight:400;font-size:24px;line-height:1}
.about-stats span{font-size:11.5px;color:var(--ink-3)}
.formnote{margin:0;padding:10px 12px;border-radius:var(--radius);font-size:12.5px}
.formnote.ok{background:color-mix(in srgb,var(--good) 16%,transparent);color:var(--good)}
.formnote.err{background:color-mix(in srgb,var(--red) 14%,transparent);color:var(--red)}
