/* landing.html — lifted verbatim from the Open Design page. */

:root{
    --red:#f25e50;
    --red-hover:#ff8d7d;
    --red-active:#cc4139;
    --dark:#111111;
    --ink:#3c3c3c;
    --muted:#5a5a5a;
    --hairline:#e6e6e6;
    --canvas:#ffffff;
    --light-bg:#f7f7f7;
    --radius:6px;
    --font:'Montserrat',system-ui,-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
  }
  *{margin:0;padding:0;box-sizing:border-box}
  body{font-family:var(--font);color:var(--ink);background:var(--canvas);line-height:1.6}
  /* height:auto — see the note in site.css. The measured width/height
     attributes reserve the space; this keeps the picture from squashing when
     max-width narrows it. */
  img{max-width:100%;height:auto;display:block}
  a{text-decoration:none}
  .wrap{max-width:1120px;margin:0 auto;padding:0 clamp(20px,4vw,40px)}
  .section{padding:clamp(56px,8vw,96px) 0}
  .section-dark{background:var(--dark);color:#fff}
  .section-light{background:var(--canvas)}
  .section-muted{background:var(--light-bg)}

  .eyebrow{display:inline-block;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--red);margin-bottom:16px}
  .section-dark .eyebrow{color:var(--red-hover)}

  h1,h2,h3{font-weight:700;line-height:1.2;letter-spacing:-.01em}
  .section-head{max-width:680px;margin:0 auto 48px;text-align:center}
  .section-head h2{font-size:clamp(24px,3.2vw,34px);margin-bottom:12px}
  .section-head p{color:var(--muted);font-size:15px}
  .section-dark .section-head p{color:#c9c9c9}
  .divider{width:56px;height:3px;background:var(--red);margin:0 auto 20px;border-radius:2px}

  .btn{display:inline-flex;align-items:center;justify-content:center;padding:14px 28px;border-radius:var(--radius);font-size:15px;font-weight:700;border:1px solid transparent;transition:background .12s ease,border-color .12s ease,color .12s ease}
  .btn-primary{background:var(--red);color:#fff}
  .btn-primary:hover{background:var(--red-hover)}
  /* Borrows the band's own text colour, so it cannot be invisible: whatever
     the surrounding words are painted in is by definition readable on that
     band. Hard-coding #fff here was right on a dark band and white-on-white on
     every light one — 107 buttons across the site rendered as empty
     rectangles, label and all. The plain `currentColor` line is the fallback
     for engines without color-mix. */
  .btn-outline{background:transparent;color:inherit;border-color:currentColor;
    border-color:color-mix(in srgb, currentColor 55%, transparent)}
  .btn-outline:hover{border-color:currentColor}
  .btn-outline-dark{background:transparent;color:var(--ink);border-color:var(--ink)}
  .btn-outline-dark:hover{border-color:var(--red);color:var(--red)}
  .btn-white{background:#fff;color:var(--red)}
  .btn-white:hover{background:#f4f4f4}
  .btn-sm{padding:10px 18px;font-size:13px}

  /* ── Hero ────────────────────────────────────────────────────────────────
     Headline beside its picture, on a ground that is built rather than left
     blank. Everything here used to be centred on flat white with the picture
     stacked on top: the h1 sat below the fold on all 66 pages that use this
     block, and the only thing separating the hero from the section under it
     was that the section had content in it.

     THE GROUND IS THREE LAYERS, none of them opaque enough to compete with the
     headline: a brand-red bloom behind the picture (so the red in the buttons
     and the eyebrow has somewhere to come from), a cool shadow low-left to
     stop the page bottoming out in pure white, and a top-lit vertical wash.
     The dot field is the same 18px grid as the product panels — it is what
     this site uses to say "a thing is standing on a surface" — and it is
     masked away before it reaches the text so it never sits behind words. */
  .hero{position:relative;overflow:hidden;
    background:
      radial-gradient(74% 62% at 82% 16%, rgba(242,94,80,.13), transparent 62%),
      radial-gradient(66% 58% at 2% 104%, rgba(17,17,17,.07), transparent 64%),
      linear-gradient(180deg, #fff 0%, #fbfbfc 46%, #f4f5f7 100%);
    border-bottom:1px solid var(--hairline)}
  .hero::before{content:"";position:absolute;inset:0;pointer-events:none;
    background:radial-gradient(#c9d0da 1.1px, transparent 1.1px) 0 0/18px 18px;
    opacity:.5;
    -webkit-mask-image:radial-gradient(58% 66% at 78% 46%, #000, transparent 72%);
            mask-image:radial-gradient(58% 66% at 78% 46%, #000, transparent 72%)}
  .hero-inner{position:relative;max-width:1120px;margin:0 auto;
    padding:clamp(40px,5.5vw,76px) clamp(20px,4vw,40px) clamp(48px,7vw,84px);
    display:grid;grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);
    gap:clamp(30px,4.6vw,64px);align-items:center}
  /* A single-column hero — a page whose data carries no image at all — must
     not leave half the grid empty with the copy squeezed into the other half. */
  .hero-inner:not(:has(.hero-image)){grid-template-columns:minmax(0,1fr);
    max-width:820px;text-align:center}
  .hero-inner:not(:has(.hero-image)) .hero-rule{margin-left:auto;margin-right:auto}
  .hero-inner:not(:has(.hero-image)) .hero-buttons,
  .hero-inner:not(:has(.hero-image)) .hero-trust{justify-content:center}

  .hero-text{text-align:left;max-width:none;margin:0;min-width:0}
  .hero-rule{display:block;width:46px;height:3px;border-radius:2px;
    background:var(--red);margin-bottom:20px}
  .hero h1{color:var(--ink);font-size:clamp(32px,4.6vw,52px);margin-bottom:18px;
    letter-spacing:-.02em}
  .hero h1 .accent{color:var(--red)}
  .hero p{color:var(--muted);font-size:clamp(15px,1.35vw,17.5px);max-width:52ch;
    margin:0 0 28px;line-height:1.72}
  .hero-buttons{display:flex;gap:14px;flex-wrap:wrap;justify-content:flex-start;
    margin-bottom:26px}
  /* Trust marks were four bare phrases in a row that read as a run-on
     sentence. As chips they read as four claims, and the red pip ties them to
     the rule above the eyebrow. */
  .hero-trust{display:flex;gap:9px;flex-wrap:wrap;justify-content:flex-start}
  .hero-trust span{display:inline-flex;align-items:center;gap:8px;
    padding:7px 14px;border-radius:999px;font-size:12.5px;color:var(--muted);
    background:rgba(255,255,255,.78);border:1px solid rgba(17,17,17,.09);
    box-shadow:0 1px 2px rgba(17,17,17,.04)}
  .hero-trust span::before{content:"";flex:none;width:6px;height:6px;
    border-radius:50%;background:var(--red)}
  .hero-trust strong{color:var(--ink);font-weight:700}

  /* `fit-content`, not a full-width flex box: the contact shadow below is
     positioned in percentages, and a percentage of the grid column is not a
     percentage of the picture. Shrink-wrapping the frame to the `<img>` makes
     the two the same box, which is what lets `--ink-*` mean anything. */
  .hero-image{position:relative;width:fit-content;max-width:100%;margin:0 auto;
    min-width:0}
  .hero-image img{max-width:100%;max-height:min(56vh,520px);width:auto;
    height:auto;display:block;position:relative;z-index:1}
  /* A photograph carries its own backdrop, and that backdrop meets the hero
     ground at a hard edge — on a dark-ground shot the edge reads as a slab
     dropped on the page. Framing it says the rectangle is the photograph's,
     not the layout's. See rule 6. */
  .hero-image img:not(.is-contained){border-radius:16px;
    box-shadow:0 18px 46px rgba(17,17,17,.16), 0 2px 6px rgba(17,17,17,.06)}
  /* A cutout has no edge to frame, so give it a floor instead: an elliptical
     contact shadow. Without it a keyed render hovers mid-band with nothing
     holding it up.

     Placed off `--ink-l/-r/-b`, which `chrome.ink_box()` measures from the
     file's alpha channel — the shadow sits under the machine's own footprint
     and at the height of its own feet, not at the arbitrary edge of whatever
     transparent margin the exporter happened to leave. The fallbacks are what
     a picture that fills its file would give. */
  .hero-image.is-cutout::after{content:"";position:absolute;z-index:0;
    left:calc((var(--ink-l,0) + var(--ink-r,1)) * 50%);
    top:calc(var(--ink-b,1) * 100%);
    transform:translate(-50%,-52%);
    width:calc((var(--ink-r,1) - var(--ink-l,0)) * 86%);height:42px;
    border-radius:50%;
    background:radial-gradient(closest-side, rgba(17,17,17,.26), transparent 76%);
    filter:blur(9px)}

  /* A wide cutout is a banner, not a column-mate: the seven-machine range shot
     is 2.06:1 and squeezing it into 45% of the grid would render each printer
     about 60px wide. It keeps the full width — but under the copy now, not
     over it, so the headline still opens the page. */
  .hero-inner--banner{grid-template-columns:minmax(0,1fr);
    gap:clamp(26px,3.5vw,44px);justify-items:center;text-align:center;
    max-width:1000px}
  .hero-inner--banner .hero-text{text-align:center;max-width:760px}
  .hero-inner--banner .hero-rule{margin-left:auto;margin-right:auto}
  .hero-inner--banner .hero-buttons,
  .hero-inner--banner .hero-trust{justify-content:center}
  .hero-inner--banner .hero-image img{max-height:min(38vh,340px)}
  .hero-inner--banner .hero-image.is-cutout::after{height:30px;
    width:calc((var(--ink-r,1) - var(--ink-l,0)) * 70%)}

  /* Pillars */
  .pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;max-width:1120px;margin:0 auto}
  .pillar-card{background:#1a1a1a;color:#fff;border:1px solid #2a2a2a;border-radius:8px;padding:36px 28px;text-align:left}
  .pillar-card .num{font-size:13px;font-weight:700;color:var(--red-hover);letter-spacing:.08em;margin-bottom:14px;display:block}
  .pillar-card h3{color:#fff;font-size:19px;margin-bottom:10px}
  .pillar-card p{color:#bdbdbd;font-size:14px;line-height:1.65}

  /* Story (zig) */
  .zig{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center;max-width:1120px;margin:0 auto}
  .zig img{border-radius:8px;width:100%}
  .zig-text h2{font-size:clamp(22px,3vw,30px);margin-bottom:16px}
  .zig-text p{color:var(--muted);font-size:15px;line-height:1.75;margin-bottom:18px}

  /* Product grid */
  .products{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;max-width:1120px;margin:0 auto}
  .product-card{background:#161616;color:#fff;border-radius:8px;overflow:hidden;display:flex;flex-direction:column}
  .product-card .thumb{aspect-ratio:1;overflow:hidden;background:#0d0d0d}
  .product-card .thumb img{width:100%;height:100%;object-fit:cover}
  .product-card-body{padding:24px 22px 28px;flex:1;display:flex;flex-direction:column}
  .product-card-body h3{color:#fff;font-size:19px;margin-bottom:6px}
  .product-card-body .tag{color:var(--red-hover);font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;margin-bottom:10px}
  .product-card-body p{color:#bdbdbd;font-size:13.5px;line-height:1.6;margin-bottom:10px;flex:1}
  .spec-list{list-style:none;margin-bottom:18px}
  .spec-list li{color:#9a9a9a;font-size:12.5px;padding:3px 0;border-top:1px solid #262626}
  .spec-list li:first-child{border-top:none}
  .spec-list b{color:#e2e2e2;font-weight:600}

  /* More families teaser */
  .family-strip{display:grid;grid-template-columns:1.1fr 1fr;gap:40px;align-items:center;max-width:1120px;margin:0 auto;background:var(--light-bg);border-radius:12px;padding:clamp(28px,4vw,48px)}
  .family-strip img{width:100%;border-radius:8px}
  .family-strip-text h2{font-size:clamp(20px,2.6vw,26px);margin-bottom:12px}
  .family-strip-text p{color:var(--muted);font-size:14.5px;line-height:1.7;margin-bottom:16px}
  .family-pills{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:20px}
  .family-pill{font-size:12.5px;font-weight:600;padding:6px 14px;border-radius:999px;border:1px solid var(--hairline);color:var(--ink);background:#fff}
  .family-pill.soon{color:var(--muted);border-style:dashed}

  /* Accessories */
  .accessories{display:grid;grid-template-columns:repeat(2,1fr);gap:28px;max-width:1120px;margin:0 auto}
  .accessory-card{display:grid;grid-template-columns:140px 1fr;gap:20px;align-items:center;border:1px solid var(--hairline);border-radius:8px;padding:20px}
  .accessory-card .thumb{aspect-ratio:1;border-radius:6px;overflow:hidden;background:var(--light-bg)}
  .accessory-card .thumb img{width:100%;height:100%;object-fit:contain;border-radius:6px}
  .accessory-card h3{font-size:17px;margin-bottom:6px}
  .accessory-card .tag{color:var(--red);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;margin-bottom:8px;display:block}
  .accessory-card p{color:var(--muted);font-size:13.5px;line-height:1.6;margin-bottom:10px}
  .accessory-card a{font-size:13px;font-weight:600;color:var(--red)}

  /* Software strip */
  .software-strip{display:grid;grid-template-columns:1fr auto;gap:clamp(24px,4vw,48px);align-items:center;max-width:1120px;margin:0 auto;background:var(--dark);color:#fff;border-radius:12px;padding:clamp(28px,4vw,48px)}
  .software-strip-text{max-width:560px}
  .software-strip-text h2{color:#fff;font-size:clamp(19px,2.4vw,24px);margin-bottom:10px}
  .software-strip-text p{color:#c9c9c9;font-size:14px;line-height:1.65}
  .software-strip-image{flex-shrink:0}
  .software-strip-image img{width:clamp(240px,28vw,380px);height:auto;border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,.35)}

  /* Table (specs comparison — factual, technical, on-brand for "engineer would trust this") */
  .spec-table-wrap{overflow-x:auto;max-width:1120px;margin:0 auto;border:1px solid var(--hairline);border-radius:var(--radius)}
  table.spec-table{width:100%;border-collapse:collapse;font-size:14px;min-width:640px}
  table.spec-table th,table.spec-table td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--hairline)}
  table.spec-table th{color:var(--ink);font-weight:700;font-size:13px;text-transform:uppercase;letter-spacing:.04em;background:var(--light-bg)}
  table.spec-table th:first-child{border-top-left-radius:calc(var(--radius) - 1px)}
  table.spec-table th:last-child{border-top-right-radius:calc(var(--radius) - 1px)}
  table.spec-table tbody tr:last-child td{border-bottom:none}
  table.spec-table tbody tr:last-child td:first-child{border-bottom-left-radius:calc(var(--radius) - 1px)}
  table.spec-table tbody tr:last-child td:last-child{border-bottom-right-radius:calc(var(--radius) - 1px)}
  table.spec-table td{color:var(--muted)}
  table.spec-table td:first-child,table.spec-table th:first-child{color:var(--ink);font-weight:600}

  /* Stat band */
  .stat-band{background:var(--red);padding:56px 0;position:relative;overflow:hidden}
  .stat-band::before{content:'';position:absolute;inset:0;background:url('https://fracktal.in/wp-content/uploads/2023/06/Volterra-IDEX-IMPTEX-machine-ISO2-0.18-Line.jpg') center/180% auto no-repeat;opacity:.1;mix-blend-mode:overlay;pointer-events:none}
  .stat-band::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,var(--red) 0%,transparent 8%,transparent 92%,var(--red) 100%);pointer-events:none}
  .stats{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;max-width:1120px;margin:0 auto;text-align:center;position:relative;z-index:1}
  .stat b{display:block;color:#fff;font-size:clamp(28px,3.4vw,40px);font-weight:700;margin-bottom:6px}
  .stat span{color:rgba(255,255,255,.9);font-size:13px}

  /* FAQ */
  .faq{max-width:820px;margin:0 auto}
  .faq details{border-bottom:1px solid var(--hairline);padding:20px 0}
  .faq summary{cursor:pointer;font-weight:600;font-size:16px;list-style:none;display:flex;justify-content:space-between;align-items:center}
  .faq summary::-webkit-details-marker{display:none}
  .faq summary::after{content:"+";font-size:20px;color:var(--red);font-weight:400;flex-shrink:0;margin-left:16px}
  .faq details[open] summary::after{content:"\2212"}
  .faq p{color:var(--muted);font-size:14.5px;margin-top:12px;line-height:1.7}

  /* CTA band */
  .cta-band{background:var(--dark);color:#fff;border-radius:16px;padding:64px clamp(24px,5vw,64px);text-align:center;max-width:1120px;margin:0 auto;position:relative;overflow:hidden}
  .cta-band h2{color:#fff;font-size:clamp(22px,3vw,30px);margin-bottom:14px}
  .cta-band p{color:#c9c9c9;font-size:15px;max-width:560px;margin:0 auto 28px}
  .cta-buttons{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}

  @media(max-width:900px){
    .pillars,.products{grid-template-columns:1fr}
    .zig{grid-template-columns:1fr}
    .zig.reverse .zig-text{order:2}
    .stats{grid-template-columns:1fr 1fr}
    .family-strip{grid-template-columns:1fr}
    .accessories{grid-template-columns:1fr}
    .software-strip{grid-template-columns:1fr;text-align:center}
    .software-strip-image{order:-1}
    .software-strip-image img{width:100%;max-width:320px;margin:0 auto}
  }

  @media(max-width:480px){
    .accessory-card{grid-template-columns:1fr;text-align:center}
    .accessory-card .thumb{max-width:160px;margin:0 auto}
  }

  /* Below ~900px the split stops paying for itself: two 340px columns give the
     headline no room and the picture no scale. One column, copy first — which
     is already the source order, so nothing has to be reordered. */
  @media(max-width:900px){
    .hero-inner,
    .hero-inner--banner{grid-template-columns:minmax(0,1fr);
      gap:clamp(24px,4vw,36px);max-width:720px}
    .hero-image img{max-height:min(42vh,380px)}
    .hero-inner--banner .hero-image img{max-height:min(30vh,260px)}
  }

  @media(max-width:600px){
    .hero-inner{padding:28px 20px 44px}
    .hero .eyebrow{font-size:11px;letter-spacing:.1em;margin-bottom:12px}
    .hero-rule{width:38px;margin-bottom:16px}
    .hero h1{font-size:29px;margin-bottom:14px;line-height:1.16}
    .hero p{font-size:15px;margin-bottom:22px;line-height:1.65}
    .hero-buttons{flex-direction:column;gap:12px;width:100%}
    .hero-buttons .btn{width:100%;padding:16px 24px}
    /* Chips stay a wrapped row — stacking them one per line turned four short
       claims into four full-width bars. `mobile.py` holds the 12px floor. */
    .hero-trust{gap:8px}
    .hero-trust span{font-size:12px;padding:6px 12px}
    .hero-image.is-cutout::after{height:30px;bottom:2%}
  }


/* ─── added by the port: chrome's own, not this page's design ──────────────
   `chrome.page()` emits a skip link on every page. Transcribed from the rule
   the material pages' stylesheet already carries, so it behaves identically
   on all three. */
.skip-link{
  position:absolute;top:-100px;left:16px;background:var(--dark);color:#fff;
  padding:10px 16px;border-radius:var(--radius);font-size:14px;font-weight:600;
  z-index:9999;text-decoration:none;
}
.skip-link:focus{top:16px;}

/* ---- Video hero (product pages: Snowflake, Twin Dragon, Volterra) ---- */
.hero-video{position:relative;min-height:74vh;display:flex;align-items:center;
  overflow:hidden;background:#0b0b0d;color:#fff}
.hero-video-bg{position:absolute;inset:0;z-index:0}
.hero-video-poster{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover}
.hero-video-frame{position:absolute;top:50%;left:50%;width:100vw;
  height:56.25vw;min-height:100%;min-width:177.78vh;
  transform:translate(-50%,-50%);border:0;pointer-events:none}
.hero-video-bg::after{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(90deg,rgba(0,0,0,.78),rgba(0,0,0,.4) 55%,
  rgba(0,0,0,.15))}
.hero-video-content{position:relative;z-index:2;width:100%;max-width:1200px;
  margin:0 auto;padding:0 clamp(1rem,4vw,4rem)}
.hero-video-content .eyebrow,.hero-video-content .overline{color:#ff5a4d}
.hero-video-content h1{font-size:clamp(2.4rem,6vw,4.6rem);line-height:1.02;
  margin:.25em 0 .3em;font-weight:800;letter-spacing:-.01em}
/* The video hero is left-aligned (text sits over the dark left scrim). The base
   centered-hero rules (`.hero p{margin:0 auto}`, buttons/trust centered) must be
   reset so the paragraph, buttons and trust marks line up under the eyebrow. */
.hero-video-content p{max-width:46ch;font-size:clamp(1rem,1.4vw,1.25rem);
  line-height:1.5;opacity:.95;margin-left:0;margin-right:0}
.hero-video .hero-buttons{display:flex;gap:.75rem;flex-wrap:wrap;
  justify-content:flex-start;margin:1.5rem 0 1rem}
.hero-video .hero-trust{display:flex;gap:1.4rem;flex-wrap:wrap;margin-top:1rem;
  justify-content:flex-start;font-size:.85rem;opacity:.92}
.hero-video .hero-trust span{white-space:nowrap}
@media (max-width:768px){.hero-video-frame{display:none}
  .hero-video{min-height:62vh}}

/* ---- In-page video embed (product demo videos) ---- */
.video-embed{position:relative;aspect-ratio:16/9;width:100%;max-width:920px;
  margin:0 auto;border-radius:14px;overflow:hidden;
  box-shadow:0 18px 50px rgba(0,0,0,.35);background:#000}
.video-embed iframe,.video-embed .video-embed-play{position:absolute;inset:0;
  width:100%;height:100%;border:0}
/* Click-to-play facade: poster fills the frame, play button centred. */
.video-embed-play{padding:0;cursor:pointer;background:#000;display:block}
.video-embed-poster{width:100%;height:100%;object-fit:cover;display:block}
.video-embed-btn{position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);width:82px;height:56px;border-radius:14px;
  background:rgba(18,18,20,.78);transition:background .16s,transform .16s}
.video-embed-btn::after{content:"";position:absolute;top:50%;left:50%;
  transform:translate(-38%,-50%);border-style:solid;border-width:12px 0 12px 20px;
  border-color:transparent transparent transparent #fff}
.video-embed-play:hover .video-embed-btn{background:var(--fracktal-red,#e11d2a);
  transform:translate(-50%,-50%) scale(1.06)}
.video-embed-play:focus-visible{outline:3px solid var(--fracktal-red,#e11d2a);
  outline-offset:3px}

/* ---- Inline looping demo video (GIF replacement) ---- */
.loop-figure{margin:0 auto;max-width:900px;text-align:center}
.loop-video{width:100%;height:auto;border-radius:14px;display:block;
  box-shadow:0 18px 50px rgba(0,0,0,.28);background:#0b0e14}
.loop-figure figcaption{margin-top:.9rem;color:var(--muted,#52525b);
  font-size:.95rem}
/* Line-art animation: white-background monoline diagrams (IDEX-vs-conventional,
   mirror, duplication). The default dark video slab turns a white line drawing
   into a glaring rectangle; this reframes it as a light technical figure —
   white ground (matching the drawing), a hairline, and only a whisper of a
   shadow — so it reads as an intentional diagram on a light or muted band. */
.loop-video.loop-line{background:#fff;box-shadow:0 2px 12px rgba(0,0,0,.06);
  border-radius:10px;border:1px solid var(--hairline,#e6e6e6)}
.loop-figure.loop-line{max-width:720px}
/* Two clips side by side (Mirror + Duplication): a pair that reads better in
   one row than stacked down the page. */
.loop-grid{display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(24px,4vw,48px);max-width:1000px;margin:0 auto;align-items:start}
.loop-cell{margin:0;text-align:center}
.loop-cell h3{font-size:clamp(1.15rem,2vw,1.45rem);font-weight:700;
  margin-bottom:1rem}
.loop-cell .loop-video{width:100%}
.loop-cell figcaption{margin-top:.9rem;color:var(--muted);font-size:.95rem}
@media(max-width:760px){.loop-grid{grid-template-columns:1fr;max-width:460px}}
/* Three clips across — the three failure modes (warp / detach / spaghetti). */
.loop-grid--3{grid-template-columns:repeat(3,1fr);max-width:1120px}
.loop-grid--3 .loop-cell h3{font-size:clamp(1.05rem,1.6vw,1.25rem);
  margin-bottom:.7rem}
.loop-grid--3 .loop-video{aspect-ratio:16/9;object-fit:cover}
@media(max-width:820px){.loop-grid--3{grid-template-columns:1fr;max-width:460px}}
/* Clip beside its text — tighter than a full-width clip with the copy below. */
.loop-split{display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(28px,5vw,60px);align-items:center;max-width:1120px;margin:0 auto}
.loop-split-media{margin:0}
.loop-split-media .loop-video{width:100%}
.loop-split-text{max-width:46ch}
.loop-split-text h2{font-size:clamp(1.5rem,2.6vw,2rem);margin:.15em 0 .55em;
  font-weight:700;line-height:1.18}
.loop-split-text p{color:var(--muted);line-height:1.7;margin-bottom:1rem}
.loop-split--rev .loop-split-media{order:2}
@media(max-width:760px){.loop-split{grid-template-columns:1fr;gap:22px}
  .loop-split--rev .loop-split-media{order:0}}
/* Plain figure: a transparent / white-background asset (a cut-out render, a
   self-titling diagram) sits directly on a matching band, not inside a
   shadowed white card that reads as a pasted screenshot. The double-class
   selector outranks `#anatomy .figure img` (which paints the white card). */
#anatomy .figure.figure-plain{max-width:960px}
#anatomy .figure.figure-plain img{border-radius:0;box-shadow:none;
  background:transparent;width:auto;max-width:100%;max-height:340px;margin:0 auto}

/* ---- Video testimonial grid (click-to-play) ---- */
.vgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2vw,22px);
  max-width:1120px;margin:0 auto}
.vtile{position:relative;display:block;padding:0;border:0;cursor:pointer;
  background:#000;border-radius:12px;overflow:hidden;text-align:left;
  box-shadow:0 10px 26px rgba(0,0,0,.12);transition:transform .16s,box-shadow .16s}
.vtile:hover{transform:translateY(-3px);box-shadow:0 16px 38px rgba(0,0,0,.2)}
.vtile:focus-visible{outline:3px solid var(--red);outline-offset:3px}
.vtile-poster{width:100%;aspect-ratio:16/9;object-fit:cover;display:block;
  opacity:.94;transition:opacity .16s}
.vtile:hover .vtile-poster{opacity:1}
.vtile-play{position:absolute;top:44%;left:50%;transform:translate(-50%,-50%);
  width:60px;height:60px;border-radius:50%;background:rgba(17,17,17,.72);
  transition:background .16s}
.vtile-play::after{content:"";position:absolute;top:50%;left:53%;
  transform:translate(-50%,-50%);border-style:solid;border-width:10px 0 10px 17px;
  border-color:transparent transparent transparent #fff}
.vtile:hover .vtile-play{background:var(--red)}
.vtile-cap{display:block;position:absolute;left:0;right:0;bottom:0;
  padding:26px 16px 13px;
  background:linear-gradient(transparent,rgba(0,0,0,.82));color:#fff}
.vtile-cap strong{display:block;font-size:14.5px;font-weight:700;line-height:1.25}
.vtile-cap span{display:block;font-size:12px;opacity:.82;margin-top:3px}
@media(max-width:820px){.vgrid{grid-template-columns:1fr;max-width:460px}}

/* ---- Spec / feature accordion ---- */
.accordion{max-width:760px;margin:0 auto;display:flex;flex-direction:column;
  gap:.6rem}
.acc-item{border:1px solid var(--line,#e4e4e7);border-radius:10px;
  background:#fff;overflow:hidden}
.acc-item summary{cursor:pointer;list-style:none;padding:1rem 1.2rem;
  font-weight:600;font-size:1.05rem;display:flex;align-items:center;
  justify-content:space-between}
.acc-item summary::-webkit-details-marker{display:none}
.acc-item summary::after{content:"+";font-weight:400;font-size:1.4rem;
  color:var(--fracktal-red,#e11d2a);line-height:1}
.acc-item[open] summary::after{content:"\2013"}
.acc-body{padding:0 1.2rem 1.1rem;color:var(--muted,#52525b);line-height:1.55}

/* Self-hosted hero video covers the band like the poster does */
.hero-video-bg video,.hero-video-el{position:absolute;inset:0;width:100%;
  height:100%;object-fit:cover;z-index:0}

/* ---- Video hero legibility: force light text + stronger scrim ---- */
/* landing.css `.hero h1/.hero p/.hero-trust` are dark; the video hero sits on
   a dark clip, so its text must be explicitly light with a soft shadow. */
.hero-video-content h1{color:#fff;text-shadow:0 2px 22px rgba(0,0,0,.5)}
.hero-video-content p{color:#fff;opacity:.96;
  text-shadow:0 1px 14px rgba(0,0,0,.45)}
.hero-video .hero-trust{color:rgba(255,255,255,.9);gap:9px}
.hero-video .hero-trust strong{color:#fff}
/* The trust marks are chips now (see `.hero-trust span` above), and a chip
   designed for a pale hero ground is a white sticker on a cinematic one. Same
   shape, inverted: smoked glass over the clip rather than a hole punched in
   it. Explicit `color` because the chip sets its own — inheriting the light
   colour from `.hero-video .hero-trust` is exactly what a direct declaration
   on the span defeats, which is the band-colour trap in reverse. */
.hero-video .hero-trust span{background:rgba(17,17,17,.44);
  border-color:rgba(255,255,255,.3);color:rgba(255,255,255,.93);
  box-shadow:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.hero-video .hero-trust span::before{background:var(--red-hover)}
/* Desktop: darkest on the left where the text sits, clearing toward the
   printer on the right. */
.hero-video-bg::after{background:linear-gradient(90deg,
  rgba(6,10,20,.9) 0%,rgba(6,10,20,.62) 42%,rgba(6,10,20,.28) 70%,
  rgba(6,10,20,.12) 100%)}
/* Heavier scrim for a busy still-photo hero (products across the whole frame):
   hold the left dark enough to carry white text over a bright package, while
   the right stays readable as product. */
.hero-video-bg.hero-scrim-heavy::after{background:
  linear-gradient(90deg,rgba(6,10,20,.93) 0%,rgba(6,10,20,.82) 34%,
  rgba(6,10,20,.5) 60%,rgba(6,10,20,.22) 100%),
  linear-gradient(180deg,rgba(6,10,20,.28),rgba(6,10,20,.1) 45%,
  rgba(6,10,20,.28))}
/* A portrait still-photo hero is cropped hard by a wide full-bleed frame — the
   product ends up zoomed-in. A taller section lets more of the shot show (and,
   showing more of the image, scales each pixel down so it reads sharper). */
.hero-video:has(.hero-scrim-heavy){min-height:82vh}
.hero-scrim-heavy .hero-video-poster{object-position:50% 42%}
@media (max-width:768px){.hero-video:has(.hero-scrim-heavy){min-height:80vh}
  .hero-scrim-heavy .hero-video-poster{object-position:50% 40%}}
/* Mobile: the printer fills the frame behind the text, so darken top-to-bottom
   across the whole width instead. */
@media (max-width:768px){
  .hero-video-content{text-align:left}
  .hero-video-content p{max-width:100%}
  .hero-video-bg::after{background:linear-gradient(180deg,
    rgba(6,10,20,.52) 0%,rgba(6,10,20,.74) 58%,rgba(6,10,20,.84) 100%)}
}

/* ---- Video lightbox (hero "Watch Video") ---- */
.video-modal{position:fixed;inset:0;z-index:9999;display:flex;
  align-items:center;justify-content:center;padding:5vw}
.video-modal[hidden]{display:none}
.video-modal-bg{position:absolute;inset:0;background:rgba(0,0,0,.86);
  backdrop-filter:blur(2px)}
.video-modal-box{position:relative;width:min(1040px,92vw);aspect-ratio:16/9}
.video-modal-frame{position:absolute;inset:0}
.video-modal-frame iframe{width:100%;height:100%;border:0;border-radius:12px;
  box-shadow:0 20px 60px rgba(0,0,0,.5)}
.video-modal-close{position:absolute;top:-2.8rem;right:0;background:none;
  border:0;color:#fff;font-size:2.4rem;line-height:1;cursor:pointer;opacity:.85}
.video-modal-close:hover{opacity:1}
/* file:// preview can't embed YouTube (Error 153); the modal still opens in
   place and shows the still + a deliberate watch action instead of a dead
   player or a hijack to a new page. On the live site the iframe plays here. */
.video-modal-fallback{position:absolute;inset:0;border-radius:12px;
  background:#0b0b0d center/cover no-repeat;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:16px;overflow:hidden;
  box-shadow:0 20px 60px rgba(0,0,0,.5)}
.video-modal-fallback::before{content:"";position:absolute;inset:0;
  background:rgba(6,8,12,.58)}
.video-modal-watch{position:relative;z-index:1;display:inline-flex;
  align-items:center;gap:12px;background:var(--red);color:#fff;
  padding:15px 28px;border-radius:12px;font-weight:700;font-size:1.05rem}
.video-modal-watch:hover{background:var(--red-hover)}
.video-modal-play{width:0;height:0;border-style:solid;
  border-width:8px 0 8px 14px;border-color:transparent transparent transparent #fff}
.video-modal-note{position:relative;z-index:1;color:rgba(255,255,255,.85);
  font-size:.9rem}

/* ---- Light product cards: transparent renders on a clean panel ---- */
/* The panel exists to flatter a picture shown whole — a transparent render, or
   a logo on its own plate. Only `.is-contained` gets that treatment. A
   photograph carries its own backdrop, so containing it paints that backdrop as
   a rectangle floating on the dots: a white-ground shot reads as letterboxing
   and a black-ground shot as a hole punched in the card. Photographs cover
   instead, and fill the frame. */
.products-light .thumb{
  background:
    radial-gradient(circle at 50% 38%, rgba(255,255,255,.95),
      rgba(255,255,255,0) 62%),
    radial-gradient(#d6dce4 1.1px, transparent 1.1px) 0 0/18px 18px,
    #eef1f5;}
.products-light .thumb img{object-fit:cover;padding:0}
/* `scale-down`, not `contain`: some partner logos are only 77px wide, and a
   mark blown up past its own pixels is worse than a mark shown small. */
.products-light .thumb img.is-contained{object-fit:scale-down;padding:26px}

/* A PALE subject needs a panel it can be seen against.
   The panel above is built for the machine renders, which measure 33-95 mean
   ink luminance and read beautifully on near-white. `pla_whitebg.webp` is a
   white lattice vase and a kraft spool at 156, and on #eef1f5 the subject and
   its background simply merged. Same dot grid, same language — a deeper,
   cooler ground and a light bloom behind the object instead of a white one,
   so the silhouette has an edge again. `chrome.ink_luma()` decides which. */
.products-light .thumb--pale-subject{
  background:
    radial-gradient(circle at 50% 40%, rgba(255,255,255,.16),
      rgba(255,255,255,0) 58%),
    radial-gradient(rgba(255,255,255,.14) 1.1px, transparent 1.1px) 0 0/18px 18px,
    linear-gradient(160deg,#3b4657 0%,#2b3340 62%,#232a35 100%);}

/* An all-photograph row: no dotted panel to show through, and a 16:10 frame
   instead of the square, which is the aspect the photographs are actually shot
   at. */
.products-photo .product-card .thumb{aspect-ratio:16/10;background:#0d0d0d}
.products-photo.prod-carousel .prod-arrow{top:104px}

/* ---- Link rail: a titled list of internal destinations ---- */
/* Twenty-eight pages had no in-content link pointing at them, the twenty city
   pages among them. This is what fixes that, so it has to look like a useful
   index and not like a footer someone moved up the page: real hit areas, a
   note that says something, and a card that responds to the pointer. */
.linkrail{list-style:none;display:grid;gap:10px;max-width:1120px;margin:0 auto;
  grid-template-columns:repeat(auto-fill,minmax(212px,1fr))}
.linkrail--wide{grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}
.linkrail a{display:flex;flex-direction:column;gap:3px;min-height:44px;
  justify-content:center;padding:12px 15px;border-radius:8px;
  background:var(--canvas);border:1px solid var(--hairline);
  color:var(--ink);transition:border-color .15s,box-shadow .15s,transform .15s}
.linkrail a:hover{border-color:var(--red);
  box-shadow:0 4px 16px rgba(242,94,80,.16);transform:translateY(-1px)}
.linkrail a:focus-visible{outline:2px solid var(--red);outline-offset:2px}
.linkrail__label{font-weight:700;font-size:14.5px;line-height:1.3}
.linkrail__note{color:var(--muted);font-size:12.5px;line-height:1.45}
/* On a dark band the card must declare its own ink — a dark surface that sets
   only a background inherits the section's colour, which is the trap that
   emptied 107 buttons. */
.section-dark .linkrail a{background:#1a1a1a;border-color:#2a2a2a;color:#fff}
.section-dark .linkrail__note{color:#bdbdbd}
@media(max-width:600px){
  .linkrail{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
  .linkrail a{padding:11px 13px}
  .linkrail__label{font-size:14px}
  .linkrail__note{font-size:12px}
}

/* ---- "Trusted by" client-logo strip ---- */
.logo-strip{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:clamp(30px,6vw,76px);max-width:1000px;margin:0 auto}
.logo-cell{display:flex;align-items:center;justify-content:center}
/* TWO caps, not one, and both of them matter.
   `height` alone made the row ragged for a reason that was not the height: a
   logo was normalised by its FILE, and half these files were transparent
   padding. `press-et.png` was 1000x500 holding 988x92 of ink, so in a 44px
   slot it drew 8 REAL PIXELS of wordmark next to a crest drawing 44. The files
   are trimmed now (rule 13), so the slot and the mark are the same thing.
   `max-width` is what stops that fix overcorrecting: trimmed, ET is 10.7:1,
   and at a shared height it would run 558px wide and swamp the row. A wordmark
   SHOULD sit shorter than a roundel — equal height is not equal weight. */
.logo-mark{height:clamp(34px,4.2vw,52px);max-width:clamp(150px,19vw,230px);
  width:auto;object-fit:contain;
  filter:grayscale(1);opacity:.55;transition:filter .2s,opacity .2s}
.logo-cell:hover .logo-mark{filter:grayscale(0);opacity:1}

/* Continuously-scrolling variant. The viewport clips + fades the edges; the
   track holds two identical logo sets and slides by exactly one set width, so
   the loop is seamless. The gap lives on each cell's right margin (not flex
   `gap`) so translateX(-50%) lands precisely on the seam. Pauses on hover;
   collapses to a static wrapped row when the user asks for less motion. */
.logo-marquee{overflow:hidden;position:relative;max-width:1160px;margin:0 auto;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.logo-track{display:flex;align-items:center;width:max-content;
  animation:logo-scroll 46s linear infinite;will-change:transform}
.logo-marquee .logo-cell{flex:0 0 auto;margin-right:clamp(40px,6vw,84px)}
.logo-marquee:hover .logo-track{animation-play-state:paused}
@keyframes logo-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .logo-track{animation:none;flex-wrap:wrap;justify-content:center;width:auto;
    max-width:1000px;margin:0 auto;row-gap:clamp(22px,3vw,32px)}
  .logo-marquee{-webkit-mask-image:none;mask-image:none}
}

/* ---- Horizontal product carousel (scroll-snap track + arrows) ---- */
/* Reuse of the materials-page printer carousel: one row, snap per card, peeks
   the next, swipes on touch. Arrows add mouse affordance; native scroll does
   the rest. The viewport clips horizontally so the page never overflows. */
.prod-carousel{position:relative;max-width:1120px;margin:0 auto}
.prod-viewport{overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;-ms-overflow-style:none}
.prod-viewport::-webkit-scrollbar{display:none}
.prod-track{display:flex;gap:28px;padding:4px 2px 8px}
.prod-track .product-card{flex:0 0 clamp(266px,80vw,324px);
  scroll-snap-align:start}
/* The chevron is an SVG, not a text glyph — see `_CHEV_R` in chrome.py for
   what was wrong with `&#8250;`. So no `font-size` and no `line-height` here:
   the icon has an explicit size and a viewBox that centres its own ink, and
   `place-items:center` puts a square in the middle of a square. Nothing about
   this depends on which font loaded. */
.prod-arrow{position:absolute;top:160px;transform:translateY(-50%);width:46px;
  height:46px;border-radius:50%;border:1px solid #d8dade;background:#fff;
  color:var(--ink);cursor:pointer;display:grid;place-items:center;padding:0;
  z-index:3;box-shadow:0 4px 16px rgba(0,0,0,.14);
  transition:color .15s,border-color .15s,background .15s,box-shadow .15s}
.prod-arrow .ui-chev{width:22px;height:22px;display:block}
.prod-prev{left:4px}.prod-next{right:4px}
.prod-arrow:hover{color:#fff;background:var(--red);border-color:var(--red);
  box-shadow:0 6px 20px rgba(242,94,80,.34)}
.prod-arrow:focus-visible{outline:2px solid var(--red);outline-offset:2px}
/* Disabled means disabled: the click is already blocked by the attribute,
   so this only has to say so. `[hidden]` needs the explicit `display:none`
   because `display:grid` above would otherwise beat the UA rule. */
.prod-arrow[hidden]{display:none}
.prod-arrow:disabled{opacity:.34;cursor:default;box-shadow:none}
.prod-arrow:disabled:hover{color:var(--ink);background:#fff;
  border-color:#d8dade;box-shadow:none}
@media(max-width:640px){.prod-arrow{display:none}}

/* ---- Full-width figure (anatomy diagram) ---- */
#anatomy .figure{max-width:1040px;margin:0 auto;text-align:center}
#anatomy .figure img{width:100%;height:auto;border-radius:14px;
  background:#fff;box-shadow:0 10px 40px rgba(0,0,0,.10)}
#anatomy .figure figcaption{margin-top:14px;font-size:14px;
  color:var(--muted,#6b7280)}

/* ---- Icon feature grid ---- */
.feature-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;
  max-width:1120px;margin:0 auto}
.feature-card{background:#161616;color:#fff;border:1px solid rgba(255,255,255,.06);
  border-radius:12px;padding:26px 22px}
.feature-icon{width:52px;height:52px;border-radius:12px;display:flex;
  align-items:center;justify-content:center;margin-bottom:16px;
  background:rgba(225,29,42,.12);color:var(--red,#e11d2a)}
.feature-icon svg{width:28px;height:28px}
.feature-card h3{color:#fff;font-size:18px;margin-bottom:8px}
.feature-card p{color:#bdbdbd;font-size:13.5px;line-height:1.6}
@media (max-width:900px){.feature-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.feature-grid{grid-template-columns:1fr}}
/* Three-up variant (e.g. the "Why PrintStick" benefit trio). */
.feature-grid--3{grid-template-columns:repeat(3,1fr);max-width:1040px}
@media (max-width:820px){.feature-grid--3{grid-template-columns:1fr;
  max-width:460px}}
/* Red-filled variant — the live product page's "applications" grid: brand-red
   cards, white icon chip and white copy. Reads as a confident feature wall on
   a light or muted band. */
.feature-grid--red .feature-card{background:var(--red);color:#fff;border-color:transparent;
  box-shadow:0 12px 30px rgba(242,94,80,.22)}
.feature-grid--red .feature-icon{background:rgba(255,255,255,.18);color:#fff}
.feature-grid--red .feature-card h3{color:#fff}
.feature-grid--red .feature-card p{color:rgba(255,255,255,.9)}

/* The inverse, for a feature grid that sits on a light or muted band. Without
   it the card keeps its near-black fill and the section reads as a different
   component from the identical grid two bands up. */
.feature-grid--light .feature-card{background:var(--canvas);color:var(--ink);
  border:1px solid var(--hairline);box-shadow:0 1px 2px rgba(17,17,17,.04)}
.feature-grid--light .feature-icon{background:rgba(242,94,80,.1);color:var(--red-active)}
.feature-grid--light .feature-card h3{color:var(--dark)}
.feature-grid--light .feature-card p{color:var(--muted)}

/* ---- Pricing comparison (two tiers + bulk band) ---- */
.price-grid{display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(20px,3vw,30px);max-width:960px;margin:0 auto}
.price-card{background:var(--canvas);border:1px solid var(--hairline);
  border-radius:16px;padding:clamp(28px,3vw,40px);display:flex;
  flex-direction:column;box-shadow:0 10px 30px rgba(0,0,0,.05)}
.price-kicker{font-size:12px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted)}
.price-name{font-size:clamp(1.3rem,2.2vw,1.6rem);font-weight:800;
  margin:.5rem 0 1rem;color:var(--dark)}
.price-amount{font-size:clamp(2rem,3.4vw,2.6rem);font-weight:800;
  color:var(--red);line-height:1}
.price-unit{font-size:1rem;font-weight:600;color:var(--muted);margin-left:.35em}
.price-desc{color:var(--muted);font-size:14.5px;line-height:1.6;
  margin:1rem 0 1.4rem}
.price-feat-head{font-weight:800;color:var(--dark);margin-bottom:.8rem}
.price-feat{list-style:none;margin:0 0 1.8rem;padding:0;display:grid;
  gap:.7rem}
.price-feat li{position:relative;padding-left:2rem;color:var(--ink);
  font-size:14.5px;line-height:1.5}
.price-feat li::before{content:"";position:absolute;left:0;top:1px;width:20px;
  height:20px;border-radius:50%;background:var(--red);
  -webkit-mask:no-repeat center/12px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  mask:no-repeat center/12px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")}
.price-btn{margin-top:auto;align-self:flex-start}
/* Highlighted premium tier — the accent-filled card. */
.price-card--hi{background:var(--red);border-color:transparent;color:#fff;
  box-shadow:0 20px 44px rgba(242,94,80,.3)}
.price-card--hi .price-kicker,.price-card--hi .price-name,
.price-card--hi .price-amount,.price-card--hi .price-feat-head{color:#fff}
.price-card--hi .price-unit,.price-card--hi .price-desc{color:rgba(255,255,255,.9)}
.price-card--hi .price-feat li{color:rgba(255,255,255,.95)}
.price-card--hi .price-feat li::before{background:#fff;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f25e50' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f25e50' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")}
.price-card--hi .price-btn.btn{background:#fff;color:var(--red)}
.price-card--hi .price-btn.btn:hover{background:rgba(255,255,255,.9)}
.price-bulk{max-width:960px;margin:clamp(20px,3vw,30px) auto 0;
  background:var(--light-bg);border:1px solid var(--hairline);border-radius:16px;
  padding:clamp(28px,3vw,40px);text-align:center}
.price-bulk h3{font-size:clamp(1.4rem,2.4vw,1.9rem);font-weight:800;
  color:var(--dark);margin-bottom:.6rem}
.price-bulk p{color:var(--muted);font-size:15px;line-height:1.6;
  max-width:60ch;margin:0 auto 1.4rem}
@media (max-width:720px){.price-grid{grid-template-columns:1fr;max-width:460px}}

/* ---- Video + copy split (how-to steps / put-it-to-the-test) ---- */
.video-split{display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(30px,5vw,64px);align-items:center;max-width:1120px;margin:0 auto}
.video-split .vsplit-media{margin:0;min-width:0}
.video-split .video-embed{max-width:none}
.vsplit-text{max-width:52ch}
.vsplit-text h2{font-size:clamp(1.6rem,2.8vw,2.1rem);margin:.15em 0 .7em}
.vsplit-text>p{color:var(--muted);font-size:15px;line-height:1.75;
  margin-bottom:1rem}
.vsplit--rev .vsplit-media{order:2}
.vsplit-steps{display:grid;gap:1.2rem}
.vsplit-step{display:flex;gap:1rem;align-items:flex-start;
  padding-bottom:1.2rem;border-bottom:1px solid var(--hairline)}
.vsplit-step:last-child{border-bottom:0;padding-bottom:0}
.vsplit-n{flex:0 0 auto;font-size:1.05rem;font-weight:800;color:var(--red)}
.vsplit-step-b h3{font-size:1.05rem;font-weight:700;color:var(--dark);
  margin-bottom:.25rem}
.vsplit-step-b p{color:var(--muted);font-size:14px;line-height:1.55}
@media (max-width:820px){.video-split{grid-template-columns:1fr;max-width:560px}
  .vsplit--rev .vsplit-media{order:0}}

/* ---------------------------------------------- the phone floor
 * See the note in site.css. 44px tap targets, 12px minimum type, measured at
 * 390px. The buttons here came out at 43px — one pixel short, which is still
 * short — and the hero eyebrow at 11px. */
@media (max-width: 640px) {
  .btn { min-height: 44px; display: inline-flex; align-items: center;
    justify-content: center; box-sizing: border-box; }
  .hero .eyebrow, .eyebrow, .overline { font-size: 12px; }
  .accessory-card .tag { font-size: 12px; }
  .skip-link { min-height: 44px; display: flex; align-items: center; }
  details.acc-item > summary { min-height: 44px; display: flex;
    align-items: center; }
}
/* Two targets this page owns that the phone floor above did not reach: the
   accessory card's "Learn more" was a bare 16px-tall link, and the FAQ
   disclosures were 32px rows. */
@media (max-width: 640px) {
  .accessory-card a { display: inline-flex; align-items: center; min-height: 44px; }
  .faq summary, .accordion summary, details > summary {
    min-height: 44px; display: flex; align-items: center;
  }
}
/* The twelve-material comparison table lives on this page too, and a link that
   IS the whole cell is a tap target, not an inline link — these were 18px tall.
   The same rule is in site.css for the material pages; this page loads
   landing.css, which is why one copy was not enough. */
@media (max-width: 640px) {
  .spec-table td a, .spec-table-wrap td a { display: block; padding: 12px 0; }
}

/* ---------- Long-form prose (the legal pages) ------------------------------
 * `.prose` had a renderer in chrome.py and no styling anywhere in the four
 * stylesheets, because until the legal pages nothing had used it. These live
 * here rather than in chrome.css: that sheet loads first on every page and is
 * deliberately `.fw-` only, so it never argues with a page stylesheet. A
 * content class defined there would start reaching pages that never asked.
 *
 * A legal document is read, not skimmed, so the measure is narrower than the
 * grid default and the leading is looser. */
/* A legal page is one document split across many sections, not many sections.
 * At the default `clamp(56px,8vw,96px)` the EULA's 25 headings put up to 192px
 * of nothing between consecutive paragraphs of the same agreement — the reader
 * scrolls past whitespace looking for the clause. Tighten the run, and collapse
 * the seam where one prose section meets the next. */
.section:has(.prose) { padding-block: clamp(24px, 3vw, 36px); }
.section:has(.prose) + .section:has(.prose) { padding-top: 0; }
.section:has(.prose) .sec-head { margin-bottom: 18px; }

.prose { max-width: 68ch; }
.prose p { margin: 0 0 1.1em; line-height: 1.75; }
.prose p:last-child { margin-bottom: 0; }
.prose-list { margin: 0 0 1.1em; padding-left: 1.35em; }
.prose-list li { margin: 0 0 .55em; line-height: 1.7; }
.prose-list li:last-child { margin-bottom: 0; }

/* `.sec-head` and `.cta__btns` exist in site.css, which the twelve material
 * pages load instead of this one. Same rule as ever: a page's stylesheet
 * REPLACES site.css, so anything a landing-family page needs has to be here
 * too. Matching site.css's values keeps the two families looking alike. */
.sec-head { max-width: 720px; margin-bottom: 40px; }
.sec-head p { color: var(--muted); margin-top: 14px; font-size: 16px; }
.cta__btns { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

/* Bare `.cta` too. This sheet had `.cta-band` and `.cta-buttons` — the landing
 * family's own names for the same idea — but the shared `cta` block emits
 * `.cta` and `.cta__btns`, which only site.css knew. Two vocabularies for one
 * component, exactly like the eyebrow/overline split further up this file. */
.cta { background: var(--dark); color: #fff; text-align: center; padding: 80px 0; }
.cta h2 { color: #fff; margin-bottom: 8px; }
.cta p { color: rgba(255,255,255,0.7); margin-bottom: 30px; }

/* ---------- cards + embed --------------------------------------------------
 * Rule 1 again: a page's stylesheet REPLACES site.css, it does not extend it.
 * The `cards` block has been rendering since the material pages were built,
 * but only site.css ever styled it — so the first landing.css page to use
 * `cards` (contact-us) drew four unstyled divs. Ported here in landing.css's
 * own tokens: it names the hairline colour --hairline where site.css calls it
 * --border, and copying the rule across verbatim would have silently produced
 * a card with no edge at all.
 */
.card-flex { display: flex; flex-wrap: wrap; gap: 20px; }
/* `cards` wraps each card's contents in .prop-body — it is the padding box
 * when the card has an image above it, and a plain passthrough when it does
 * not. It still needs a rule, or the class-coverage gate reports the element
 * as entirely unstyled, which is the check doing its job. */
.prop-body { display: block; }
.prop-card {
  width: calc(33.333% - 14px);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 22px 24px;
  background: var(--canvas);
  transition: border-color .12s ease;
}
.prop-card:hover { border-color: var(--muted); }
.prop-card .name {
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted);
}
.prop-card .ctx {
  font-size: 18px; font-weight: 600; color: var(--dark);
  margin: 6px 0 12px; line-height: 1.35;
}
.prop-card ul { list-style: none; display: grid; gap: 7px; }
.prop-card li {
  font-size: 14px; color: var(--ink); line-height: 1.5;
  padding-left: 14px; position: relative;
}
.prop-card li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--red);
}
@media (max-width: 900px) { .prop-card { width: calc(50% - 10px); } }
@media (max-width: 560px) { .prop-card { width: 100%; } }

/* The form the `embed` block drops in belongs to Fluent Forms, so this styles
 * the CONTAINER and leaves the widget's own CSS alone — restyling a plugin's
 * internals from here is how a plugin update silently breaks a contact page. */
.embed { max-width: 720px; }
.embed-placeholder {
  border: 1px dashed var(--hairline); border-radius: var(--radius);
  padding: 20px 22px; color: var(--muted); font-size: 14px;
}
.embed-placeholder code {
  display: block; margin-top: 8px; font-size: 13px; color: var(--dark);
}
