/* =====================================================================
   Homepage-only styles. Shared tokens, header, footer, tiles, ticker,
   pills, cards and the paywall tile live in mesteel.css — never redefine
   them here. Values lifted verbatim from design/homepage.html.
   ===================================================================== */

/* ---------- Hero ---------- */
/* `var(--hero-img, …)` with the built-in picture as the FALLBACK: the page
   sets the property only when Admin has been given one, so a stylesheet
   that is served to a page which does not set it looks exactly as it did.
   See Modules\Web\Services\HeroImages. */
.hero{position:relative;height:680px;
  background:var(--hero-img,url(../img/hero-warehouse.jpg)) var(--hero-pos,center)/cover}
.hero:before{content:"";position:absolute;inset:0;z-index:0;background:linear-gradient(90deg,rgba(255,255,255,.92) 0%,rgba(255,255,255,.75) 40%,rgba(255,255,255,.15) 75%,rgba(255,255,255,0) 100%)}
.hero:after{content:"";position:absolute;left:0;right:0;bottom:0;height:140px;background:linear-gradient(180deg,rgba(255,255,255,0),#fff)}
/* --z-raised: the homepage hero carries the search box and its combos. */
.hero>*{position:relative;z-index:var(--z-raised)}
.hero h1{font-size:64px;line-height:1.02;letter-spacing:-.03em;margin:20px 0 18px;max-width:760px;text-wrap:balance}
.hero p{margin:0 0 30px;font-size:17px;line-height:1.55;color:#475569;max-width:520px}

/* ---------- Hero search ---------- */
.search{width:820px;background:#fff;border-radius:20px;padding:8px;box-shadow:0 24px 70px rgba(15,31,74,.18),0 0 0 1px rgba(15,31,74,.06)}
.tabs{display:flex;gap:2px;padding:6px 8px 10px;font-size:13.5px;font-weight:700}
.tabs button{border:0;background:none;font:inherit;padding:8px 16px;border-radius:999px;color:var(--mute);cursor:pointer}
.tabs button:hover{background:var(--blue-10);color:var(--blue);transform:none}
.tabs button.on,.tabs button.on:hover{background:var(--blue);color:#fff}
.fields{display:grid;grid-template-columns:1.5fr 1fr 1fr auto;gap:6px}
.field{background:var(--bg);border-radius:14px;padding:14px 18px}
.field label{display:block;font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
.field input,.field select{width:100%;border:0;background:none;font:inherit;font-size:16px;font-weight:700;margin-top:4px;color:var(--ink);outline:0;padding:0}
.field select{appearance:none;color:var(--faint)}
.field select.set{color:var(--ink)}
.fields .btn{border-radius:14px;padding:0 30px;font-size:15px}
.chips{display:flex;gap:8px;margin-top:16px;font-size:13px;font-weight:600;color:#334155;align-items:center}
.chips span{color:var(--mute)}
.chips a{background:#fff;border:1px solid #DDE4F0;padding:6px 13px;border-radius:999px;color:#334155}

/* ---------- Two-column panels ---------- */
.two{display:grid;grid-template-columns:1.6fr 1fr;gap:24px;padding-top:32px}
.panel{border-radius:24px;padding:28px}
.panel .sec-h h2{font-size:24px}
.panel .sec-h{margin-bottom:18px}

.offers{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.offer{background:#fff;border-radius:16px;padding:16px;display:flex;flex-direction:column;gap:8px;box-shadow:var(--shadow)}
.offer .top{display:flex;justify-content:space-between;align-items:center}
.offer .top time{font-size:12px;color:var(--faint)}
.offer b{font-size:15px}
.offer .m{font-size:13px;color:var(--mute)}
.offer .lock{font-size:12.5px;color:var(--faint)}

.price{display:grid;grid-template-columns:1fr 80px auto;gap:12px;align-items:center;padding:12px 0;border-top:1px solid #F1F5F9;font-variant-numeric:tabular-nums}
.price b{font-size:14px;display:block}
.price small{font-size:12px;color:var(--faint)}
.price .v{text-align:right}
.price .v b{font-size:16px}
.price .v small{font-weight:700}
.price .v .up{color:#16A34A}
.price .v .dn{color:var(--red)}

/* Empty states — shown until price_data / offers have rows */
.empty{background:#fff;border:1px dashed var(--line);border-radius:14px;padding:22px 18px;text-align:center;color:var(--mute);font-size:13.5px;line-height:1.6}
.empty b{display:block;color:var(--ink);font-size:14.5px;margin-bottom:4px}

/* ---------- Featured companies + news ---------- */
.two2{display:grid;grid-template-columns:1fr 1fr;gap:24px;padding:24px 0 32px}
.co{padding:16px 18px;display:flex;gap:14px;align-items:center;border-radius:18px}
.co b{display:block;font-size:15.5px}
.co small{font-size:13px;color:var(--mute)}
.news{border-radius:18px;overflow:hidden}
.news article{padding:16px 18px;border-bottom:1px solid #F1F5F9}
.news article:last-child{border:0}
.news time{display:block;font-size:11.5px;color:var(--faint);font-weight:700;margin-bottom:5px}
.news b{font-weight:700;font-size:15px;line-height:1.4}
.news a{color:inherit;display:block}
.news a:hover b{color:var(--blue)}

/* ---------- Membership ---------- */
.member{margin:16px 0 48px;background:linear-gradient(135deg,var(--blue),var(--navy));border-radius:28px;padding:48px;color:#fff;display:grid;grid-template-columns:1.1fr 1fr 1fr;gap:28px;align-items:center}
.member .kick{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#93A9E8}
.member h2{font-size:38px;line-height:1.05;letter-spacing:-.03em;margin:12px 0}
.member p{margin:0;font-size:14.5px;line-height:1.6;color:#B8C4E6}
/* Two treatments on the dark membership band, named after what they look
   like and not after a plan. `.ghost` was `.brief` — the withdrawn tier's
   name, still on the slot after that slot started showing Premium, which is
   how removing one class from the markup made the card transparent and
   unreadable. A treatment class that names a product goes stale the first
   time the product does. */
.plan{border-radius:20px;padding:24px;position:relative;overflow:hidden}
.plan.full{background:#fff;color:var(--ink)}
.plan.ghost{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2)}

/* The plan's metal, the same 4px bar the dashboard card and the plan
   chooser use. Keyed on the plan code via data-plan. */
.plan[data-plan]::before{content:"";position:absolute;inset:0 0 auto;height:4px}
.plan[data-plan="full"]::before{
  background:linear-gradient(90deg,var(--silver-lo),var(--silver-hi) 50%,var(--silver-lo))}
.plan[data-plan="premium"]::before{
  background:linear-gradient(90deg,var(--gold-lo),var(--gold-hi) 50%,var(--gold-lo))}
/* `.plan .row` was here — the flex row that held the plan name beside the
   "POPULAR" chip. Both are gone; a lone heading needs no layout. */
.plan .amt{font-size:40px;font-weight:800;margin:10px 0 0;letter-spacing:-.03em}
.plan .amt small{font-size:14px;font-weight:600;color:var(--mute)}
.plan.ghost .amt small{color:#B8C4E6}
.plan .note{font-size:12.5px;color:var(--mute);margin-bottom:14px}
.plan.ghost .note{color:#B8C4E6}
.plan ul{list-style:none;margin:0;padding:0;font-size:13.5px;line-height:1.9;color:#334155}
.plan.ghost ul{color:#DCE3F5}
.plan .btn{width:100%;margin-top:16px}
/* The outline treatment for a button on the dark band — but NOT for a metal
   one. `.plan.ghost .btn` is three classes and `[data-plan] .btn-metal` is
   two, so without this exclusion the ghost rule wins and a metal button
   renders as a white outline. */
.plan.ghost .btn:not(.btn-metal){background:none;border:1.5px solid rgba(255,255,255,.5);color:#fff}

/* ---------- The three rows the home page opens with ----------
   Row 1 is the newsroom beside the prices box, row 2 the featured
   companies, then the two search strips and the offers panel.

   `.hm-top` is 2fr 1fr rather than `.two`'s 1.6fr 1fr: the news column
   carries a standfirst and a thumbnail and needs the width, and the prices
   box is three rows of figures that does not. One column below 1023px,
   where the whole page stacks. */
.hm-top{display:grid;grid-template-columns:2fr 1fr;gap:24px;padding-top:32px;align-items:start}
.hm-news{min-width:0}          /* a grid item defaults to auto, and a long
                                  headline would push the prices box off */
.hm-list{display:flex;flex-direction:column}
.hm-item{display:flex;gap:16px;align-items:flex-start;
  padding:14px 0;border-top:1px solid var(--line)}
.hm-list>.hm-item:first-child{border-top:0;padding-top:0}
.hm-txt{flex:1;min-width:0;color:inherit;display:block}
.hm-txt b{display:block;font-size:16.5px;line-height:1.35;color:var(--ink);margin:2px 0 4px;
          transition:color .15s ease}
.hm-txt p{font-size:13.5px;line-height:1.5;color:var(--mute);margin:0}
/* ---------- The news row answers with its TITLE ----------
   These rows carried `.lift` and no longer do: a 1.02 scale and a 28px
   shadow is right for a company card, which is an object you pick up,
   and wrong for a stack of headlines somebody is SCANNING — six rows
   moving under the pointer in turn is a restless page. The tokens are
   untouched, so the featured carousel below keeps its lift.

   The whole row is inside this anchor, so hovering anywhere in the card
   hovers it, and the thumbnail is a second anchor with `tabindex=-1`. */
.hm-txt:hover b,
.hm-txt:focus-visible b{color:var(--blue)}
.hm-txt:focus-visible{outline:2px solid var(--blue);outline-offset:3px;
  border-radius:10px}
.hm-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-size:11.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--mute)}
.hm-place{display:inline-flex;align-items:center;gap:5px}
.hm-place .flag{width:18px;height:13px}
.hm-prem{color:#92400E;background:#FEF3C7;border-radius:999px;padding:2px 8px;letter-spacing:.02em}
.hm-thumb{flex:none;width:120px;height:80px;border-radius:12px;overflow:hidden;background:var(--bg)}
.hm-thumb img{width:100%;height:100%;object-fit:cover;display:block}

/* The right-hand column. `align-content:start` so the two cards sit at the
   top of it rather than being spread down the news column's full height —
   the column is a grid item and `.hm-top` stretches its children. */
.hm-side{display:grid;gap:22px;align-content:start;min-width:0}

/* ---------- Featured companies: the carousel ----------
   A full-width row again, and a real scrolling box rather than a grid.

   HOW MANY ARE VISIBLE is `--cards`, and the card's width is derived from
   it. That is the only way "four at 1440, three at 1024, two at 768, one
   at 360" can be stated once: four numbers in four media queries, and one
   piece of arithmetic that reads them.

   The percentage resolves against `.hm-lane`, whose width is the
   scroller's own content width — which is why the cards are flat in the
   lane with no per-run wrapper between them. A wrapper would be
   content-sized and the percentage would be circular.  */
.hm-feat{--cards:4;--cgap:14px;padding:28px 0 4px}

/* The scroller. `overflow-x:auto` is what makes a swipe work on a touch
   screen with no handler of our own — the browser's own momentum, which
   nothing hand-written matches. The bar is hidden because the arrows and
   the drift are the affordance; the box is still scrollable by every
   other means, including a trackpad and a keyboard. */
/* NO SCROLL SNAPPING, AND THAT IS NOT A PREFERENCE.
   A snap point re-snaps EVERY scroll, and the drift is a scroll — so with
   `scroll-snap-type:x proximity` each sub-pixel step was pulled straight
   back to the nearest card edge and the strip never moved at all. Measured
   in Chrome: `scrollLeft = 40` read back as 0, while exactly one card's
   width (300) stuck, because that landed on a snap point.

   `mandatory` is worse, not better. The arrows move by exactly one card
   anyway, which is what snapping would have been for. */
/* PADDED, AND PULLED BACK BY THE SAME AMOUNT.

   `overflow-x:auto` clips at the PADDING box, and `overflow-y` cannot be
   left visible beside it — per spec a non-visible value on one axis makes
   the other compute to `auto` — so the only way a card’s shadow survives
   is for the box to be bigger than the card. Measured before the fix, at
   every width:

     at rest     12px of the shadow cut at the bottom, 8px at the top,
                 10px at each side
     on hover    the card is `scale(1.02)`, so it grows ~2.4px past the
                 top — which is what cut the gold bar off the MEGATE card
                 — and its `0 12px 28px` shadow reaches 40px below

   The negative margin is what keeps the section’s spacing and the cards’
   alignment with the heading exactly as they were: the padding box grows
   outwards and the content box does not move.

   THE BOTTOM IS 44px AND THE TOP IS 24px, and they are different
   numbers because the shadow is not symmetrical: `0 12px 28px` reaches
   **40px below** the card and only 16px above it, and `scale(1.02)`
   adds ~2.4px to each. Measured at 768, 1024 and 1440 with a real
   pointer on a card: 40 of reach against 22 of room — **18px cut at
   the bottom**, and 16 against 22 at the top, which was already clear
   by 6px. 44 covers the 42.4 the bottom needs.

   An earlier revision called that 18px a deliberate cost, on the
   ground that the pull would put the scroller's own hit area over the
   section below. That is worth checking rather than assuming, and it
   is not what happens: the next section is a LATER sibling, so it
   paints over the overflowing padding box and takes the clicks.
   `document.elementFromPoint` 2px under the clip box returns
   `SECTION.sec` at every width, before and after.

   THE TOP IS NOT RAISED. It needs nothing — and 14px above it are
   the two arrows and "View all", which a taller box would cover.

   THE HORIZONTAL PULL IS WIDTH-AWARE, and that is not tidiness: `.wrap`
   has a 16px gutter below 640, so a 20px pull there puts the scroller 4px
   wider than the viewport and the PAGE scrolls sideways — which is the
   one thing this section is measured against. */
.hm-car{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none;
  -webkit-overflow-scrolling:touch;
  padding:24px 20px 44px;margin:-24px -20px -44px}
.hm-car::-webkit-scrollbar{display:none}

/* NO MASK FADE AT THE EDGES, and the reason is the shadow this round
   exists to show. A `mask-image` clips the paint, so a 24px fade would
   erase the side shadows the 20px padding was added to reveal — the fade
   and the shadow want the same 20px. And at rest the first card is
   aligned with the heading, so on the left there is nothing scrolling out
   to soften: a gradient there reads as a card that has lost its edge. */

/* Width AUTO, deliberately: as the only child of the scroller it takes the
   visible width, which is what the cards' percentage needs. The cards
   overflow it, and that overflow is the scroll. */
.hm-lane{display:flex;gap:var(--cgap);align-items:stretch}

.hm-feat .hm-lane > .hm-fc{
  flex:0 0 calc((100% - (var(--cards) - 1) * var(--cgap)) / var(--cards))}

/* The two arrows, in the section head beside "View all". The site's round
   control, the same 30px shape as the ticker's charts link. */
.hm-arrows{display:inline-flex;gap:8px;margin-left:14px}
.hm-arrow{flex:none;width:32px;height:32px;border-radius:999px;
  border:1px solid var(--line);background:#fff;color:var(--ink);
  display:grid;place-items:center;cursor:pointer;padding:0}
.hm-arrow svg{width:15px;height:15px}
.hm-arrow:hover{background:var(--bg);border-color:var(--blue);color:var(--blue);transform:none}
.hm-arrow:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* NO DRIFT WHEN THE VISITOR HAS ASKED FOR NONE. The JavaScript reads the
   same query and never starts the loop, so this is belt as well as
   braces — and it is what stops a SNAP animating too, which is the one
   piece of motion left in the box. */
/* NO DRIFT WHEN THE VISITOR HAS ASKED FOR NONE — the component reads the
   same query and never starts the loop, so this rule is what says so in the
   stylesheet as well, and what stops the box smooth-scrolling under an
   arrow press. The arrows still work: that is the brief, and it is the
   reason this is `scroll-behavior` and not `display:none`. */
@media (prefers-reduced-motion:reduce){
  .hm-car{scroll-behavior:auto}
}
/* ---------- The featured card ----------
   A COLUMN, not `.co`'s row. `.co` is the directory sidebar's row shape and
   this card carries a logo, a two-line name, an activity, a place with its
   flag and a row of product tags — four things that will not share a line.

   `align-items:stretch` on `.hm-lane` already makes every card as tall as
   the tallest, so equal height is the grid's and not arithmetic here. What
   this adds is the two things that make equal height USEFUL: the name is
   clamped so one long one cannot set the height for eleven others, and the
   tag row is pushed to the bottom so the tags line up across the strip
   whatever the name above them wrapped to. */
.hm-feat .hm-fc{display:flex;flex-direction:column;gap:8px;
  padding:16px 16px 14px;border-radius:18px}

/* The logo and the tier badge, on one line with the badge to the right. */
.hm-feat .fc-head{display:flex;align-items:flex-start;justify-content:space-between;
  gap:10px;margin-bottom:2px}
.hm-feat .fc-head .avatar{width:52px;height:52px;border-radius:12px;flex:none;
  font-size:16px}
/* `.avatar.img` is the directory's own class for "this one holds a picture":
   no tint, no letter spacing, and the file fitted rather than cropped so a
   wide wordmark is not sliced down to its middle third. */
.hm-feat .fc-head .avatar.img{background:#fff;border:1px solid var(--line);padding:4px}
.hm-feat .fc-head .avatar img{width:100%;height:100%;object-fit:contain;display:block}
.hm-feat .fc-head .pill{flex:none}

/* TWO LINES, AND THE CLAMP IS THE POINT. The names here run from "WINOA" to
   "AL GURG BUILDING SERVICES CO. LTD. (L.L.C.)" — 43 characters, which at
   this width is four lines. Clamped it is two, so the card's height is set
   by its content and not by its longest tenant. */
.hm-feat .fc-name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;font-size:15px;line-height:1.3;min-height:2.6em}

/* The activity and the place are one line each, ellipsised. Two lines of
   either would reintroduce the variation the clamp above just removed. */
.hm-feat .fc-act,
.hm-feat .fc-place{display:block;font-size:12.5px;color:var(--mute);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hm-feat .fc-place{display:flex;align-items:center;gap:6px;min-width:0}
.hm-feat .fc-place .flag{flex:none;width:18px;height:13.5px}
.hm-feat .fc-where{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* `margin-top:auto` is what lines the tag rows up across the strip. */
.hm-feat .fc-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:auto;padding-top:4px}
.hm-feat .fc-tag{font-size:11px;line-height:1;padding:5px 8px;border-radius:999px;
  background:var(--bg);color:var(--ink-2,var(--mute));border:1px solid var(--line);
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hm-feat .fc-tag.more{background:var(--blue-10);border-color:transparent;
  color:var(--blue);font-weight:600}

/* One card per row below 640, where the lane is the full width: the tags get
   two lines there rather than being cut to one each. */
/* The clamp is NOT re-declared here, and that is deliberate: it was, at
   the same value as the base rule, which is dead weight AND it defeated the
   test for it — a regex for the selector matched this copy and passed while
   the base rule had been sabotaged. Every rule for a selector, not the
   first, is a trap this project has recorded before. */
@media (max-width:639px){
  .hm-feat .hm-fc{padding:14px}
}

/* ---------- The sidebar box advert ----------
   `HOME_BOX`, 300x250 sold, and it SCALES to the column: at 1440 the
   column is 387px, so a 300px creative in a fixed 300px box would sit
   off-centre with a gap beside it. `width:100%` with the slot's own
   aspect ratio keeps the shape the advertiser bought at whatever width
   the column happens to be.

   IT CARRIES THE PLACEHOLDER NOW and is no longer `hidden` when empty,
   so the box wears `.ad` as well and takes its dashed outline, its
   striped ground and its centring from there. What stays here is only
   what is this column's: the 16px radius its neighbours have, and the
   aspect ratio that keeps the shape the advertiser bought at whatever
   width the column happens to be.

   `background` is NOT restated. It was `var(--bg)`, which at (0,1,0)
   against `.ad`'s own (0,1,0) wins on load order — home.css is second —
   and would have flattened the placeholder's stripes on this one box
   while every other slot on the site kept them. */
.hm-ad{width:100%;aspect-ratio:300/250;border-radius:16px;overflow:hidden}
.hm-ad .ad-link,
.hm-ad img{display:block;width:100%;height:100%}
.hm-ad img{object-fit:contain}

.hm-offers{padding-top:24px}

/* The brief's four counts. 1200 rather than 1024 for the first step down,
   because at 1024 the row is 976px and four cards of 235px are narrower
   than the name on most of them. */
@media (max-width:1200px){ .hm-feat{--cards:3} }
@media (max-width:1023px){ .hm-feat{--cards:2} }
@media (max-width:639px){
  .hm-feat{--cards:1}
  /* `.wrap` drops to a 16px gutter here, so 20px of pull would push the
     scroller past the viewport. 12px leaves 4px and still clears the
     resting side shadow, which measured 10px. */
  .hm-car{padding-left:12px;padding-right:12px;margin-left:-12px;margin-right:-12px}
}

@media (max-width:1023px){
  .hm-top{grid-template-columns:1fr}
  .hm-side{gap:18px}
}
@media (max-width:639px){
  /* The thumbnail is the first thing to go: 120px of a 328px row leaves a
     headline wrapping two words to a line. */
  .hm-thumb{width:84px;height:60px}
  .hm-txt b{font-size:15.5px}
}

/* ---------- Responsive ---------- */
@media (max-width:1023px){
  .hero{height:auto;padding-bottom:48px}
  .hero .wrap{padding-top:112px}
  .hero h1{font-size:48px}
  .search{width:100%}
  .fields{grid-template-columns:1fr 1fr}
  .fields .btn{grid-column:1/-1;padding:14px;min-height:52px}
  .two,.two2{grid-template-columns:1fr}
  .member{grid-template-columns:1fr;padding:32px}
  .plan .btn{min-height:48px}
}
@media (max-width:639px){
  .hero .wrap{padding-top:96px}
  .hero h1{font-size:36px;margin:16px 0 14px}
  .hero p{font-size:15px;margin-bottom:22px}
  .hero:before{background:linear-gradient(180deg,rgba(255,255,255,.97) 0%,rgba(255,255,255,.88) 60%,rgba(255,255,255,.7) 100%)}
  .search{border-radius:16px}
  .tabs{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .tabs::-webkit-scrollbar{display:none}
  /* Reference sets 40px here, below the 44px minimum design/README.md
     mandates for mobile tap targets. */
  .tabs button{white-space:nowrap;min-height:44px}
  .fields{grid-template-columns:1fr}
  .chips{flex-wrap:wrap}
  .chips a{min-height:36px;display:inline-flex;align-items:center}
  .offers{grid-template-columns:1fr}
  .panel{padding:20px;border-radius:20px}
  .member{padding:24px;border-radius:22px;gap:16px}
  .member h2{font-size:30px}
  .price{grid-template-columns:1fr auto}
  .price svg{display:none}
}

/* ---------- Hero search comboboxes ----------
   Country and Activity are mesteel.combo() now, not native selects; the
   panel lives in mesteel.css and this only fits it to the .field shell. */
.field .lbl{display:block;font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mute)}
.field .combo-row{margin-top:4px}
.field .combo-row input{margin-top:0}
.field.combo.is-open{box-shadow:0 0 0 2px var(--blue),0 0 0 5px rgba(31,63,143,.12)}

/* ---------- Price ticker ----------
   Replaces the "ME INDICES" strip. It keeps that strip's clothes — the navy
   pill, the shadow, the tabular numerals, all of `.ticker` in mesteel.css —
   and adds a fixed switch on the left, a moving lane in the middle and a
   pause control on the right.

   `.ticker` sets `gap:28px`, which is right between five loose spans and
   wrong between three structural parts; the gap is reset here and each part
   spaces itself. */
.pt{gap:0;padding:8px 10px 8px 12px;overflow:hidden}

/* The switch. Fixed: it never scrolls with the prices. */
.pt-sw{display:flex;gap:2px;flex:none;background:rgba(255,255,255,.10);
  border-radius:999px;padding:3px}
.pt-sw button{border:0;background:none;font:inherit;font-size:12px;font-weight:700;
  letter-spacing:.04em;color:#C3D0F2;padding:6px 14px;border-radius:999px;
  cursor:pointer;white-space:nowrap}
.pt-sw button:hover{background:rgba(255,255,255,.12);color:#fff;transform:none}
.pt-sw button.on,.pt-sw button.on:hover{background:#fff;color:var(--navy)}
.pt-sw button:focus-visible{outline:2px solid #fff;outline-offset:2px}

/* The window the lane slides behind. `min-width:0` because this is a flex
   item and a flex item's default is `auto`, so without it the lane's full
   width pushes the pause button off the end of the strip — the same trap
   `.pr-scroll` on the price tables already records — it was the pause
   button that got pushed off the end, and now it is the charts link. */
.pt-view{flex:1;min-width:0;overflow:hidden;margin:0 10px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 24px,#000 calc(100% - 24px),transparent);
          mask-image:linear-gradient(90deg,transparent,#000 24px,#000 calc(100% - 24px),transparent)}

/* Two identical runs side by side; the lane slides by exactly half its own
   width and starts again, which is what makes the loop seamless. The
   duration is set from the measured content width so the speed is constant
   whatever is in it — see mesteel.priceTicker(). */
.pt-lane{display:flex;width:max-content;
  animation:pt-roll var(--pt-dur,40s) linear infinite}
/* PAUSE ON HOVER, AND ON KEYBOARD FOCUS -- `:has(:focus-visible)` and not
   `:focus-within`. Clicking the pause button FOCUSES it, so with
   `:focus-within` the strip stayed paused when you pressed play again and
   the control read as broken: measured as "after pressing play -> paused",
   and it only resumed on blur. A keyboard user tabbing through the links
   still needs it to stop, and that is exactly what :focus-visible is. */
.pt:hover .pt-lane,
.pt:has(:focus-visible) .pt-lane{animation-play-state:paused}
@keyframes pt-roll{from{transform:translateX(0)}to{transform:translateX(-50%)}}

.pt-run{display:flex;align-items:center;flex:none}

/* One item. The divider is a border rather than a gap, so it sits between
   items and never at the end of a run. */
.pt-i{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  padding:6px 18px;color:#fff;border-left:1px solid rgba(255,255,255,.16);
  font-size:13px;font-weight:700}
.pt-run>.pt-i:first-child{border-left:0}
/* HOVER HAS TO RESTATE THE COLOUR, and that is the whole bug.
   `a:hover{color:var(--navy)}` in mesteel.css is (0,1,1) and `.pt-i` is
   (0,1,0), so on hover every item took the NAVY the strip is painted in:
   the price and the change went invisible against their own background.
   Measured in Chrome — the hovered item's text was `rgb(15,31,74)` on
   `rgb(15,31,74)`.
   `.pt .pt-i:hover` is (0,2,1) and wins wherever this sheet loads. The
   wash is lifted so the row still reads as hovered, and the product name
   is underlined, so the state is not carried by a background alone. */
.pt .pt-i:hover{background:rgba(255,255,255,.16);border-radius:10px;transform:none;color:#fff}
.pt .pt-i:hover .pt-n{color:#fff;text-decoration:underline}
.pt .pt-i:hover .pt-d{color:#C9D6F5}
.pt .pt-cta:hover{color:#fff}
.pt-i:focus-visible{outline:2px solid #fff;outline-offset:-2px;border-radius:10px}
.pt-n{color:#E4EAFA;font-weight:600}
.pt-v{font-variant-numeric:tabular-nums}
.pt-c{font-size:12px;font-weight:700}
.pt-c.up{color:var(--up)}
.pt-c.down{color:var(--dn)}
.pt-c.flat{color:#93A9E8}
.pt-d{font-size:11px;font-weight:600;color:#93A9E8}
.pt-lock{display:inline-flex;color:#93A9E8}
.pt-lock svg{width:13px;height:13px;fill:currentColor}
.pt-cta{color:#FFD775}
.pt-cta:hover{color:#fff}

/* The one round control at the end: the way out to the charts. There was a
   pause/play button beside it and it is gone — hover, keyboard focus and
   `prefers-reduced-motion` already stop the strip, in the three rules above,
   and a fourth way to do it was a control to notice and press on a strip
   meant to be read in passing. `.pt-play` is deleted from this sheet, the
   markup and home.js together; `paused` went with it.

   `.pt-more` is a LINK, so it keeps the colour it is given here for the
   same (0,1,1) reason as `.pt-i` above. */
.pt .pt-more{flex:none;border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.18);color:#fff;
  width:30px;height:30px;border-radius:999px;display:grid;place-items:center;
  cursor:pointer;padding:0}
.pt .pt-more:hover{background:rgba(255,255,255,.3);transform:none;color:#fff}
.pt .pt-more:focus-visible{outline:2px solid #fff;outline-offset:2px}
.pt .pt-more svg{width:15px;height:15px}

/* NO MOVEMENT AT ALL when the visitor has asked for none — a static row they
   can push sideways instead. The second run is removed rather than left in
   place: with nothing moving it is just every price listed twice. */
@media (prefers-reduced-motion:reduce){
  .pt-lane{animation:none;width:auto}
  .pt-run[aria-hidden="true"]{display:none}
  .pt-view{overflow-x:auto;scrollbar-width:thin;
    -webkit-mask-image:none;mask-image:none}
}

/* Phones. The switch stays visible and goes ABOVE the strip rather than
   shrinking: at 360 a row of Prices | Futures plus a lane plus a button
   leaves the lane about 120px, which is not a ticker. */
@media (max-width:719px){
  .pt{flex-wrap:wrap;border-radius:18px;margin-top:-10px;padding:10px}
  .pt-sw{order:1}
  .pt .pt-more{order:2;margin-left:auto}
  .pt-view{order:3;flex:1 0 100%;margin:8px 0 0}
  .pt-i{font-size:12px;padding:5px 12px;gap:6px}
  .pt-d{display:none}
}
