/* TumaPlug public site.
 *
 * Palette and hierarchy come from brand/tokens.css and are inlined here so the
 * page needs one stylesheet rather than two round trips.
 *
 *   60-70%  warm sand canvas   most of the page
 *   20-25%  black / charcoal   nav, footer, two feature bands
 *    5-10%  gold               CTAs, step numbers, small accents only
 *
 * Gold is jewellery. There is deliberately no large gold fill anywhere below.
 */

:root {
  /* NEUTRAL blacks. The brand values #0B0C0C and #171818 both have a red
     channel BELOW green and blue, which is a faint cyan cast — against warm
     gold and sand canvas that reads as murky rather than black. Equalising the
     channels (and warming them a touch, since everything around them is warm)
     gives a black that actually reads as black. The brand token is unchanged
     for print and the logo; this is the screen rendering of it. */
  --black:#0A0A0A; --gold:#DFB357; --gold-hi:#EDC15E; --white:#EDEDED;
  --canvas:#F7F4EC; --gold-tint:#F5E9CD; --dark:#121212;
  --text:#171717; --muted:#686866; --line:#E5E0D6;
  --surface:#FFFDF8; --line-dark:rgba(237,237,237,.14);
  --r:14px; --r-lg:22px; --pill:999px;
  --shadow:0 16px 40px -30px rgba(23,23,23,.5);
  --font:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;

  /* ---- Fluid scale ------------------------------------------------------
     Every size below is a straight line through two points: the value at a
     360px phone and the value at a 1280px desktop, with clamp() holding it
     there beyond both ends. The page had two breakpoints, so a 320px Android
     and a 430px Pro Max rendered the same 16px/24px button — correct for the
     larger, oversized on the smaller, and nothing in between ever adjusted.
     Continuous scaling means there is no width at which the layout is merely
     tolerated.

     Every line is calibrated 320px -> 1280px, NOT 360 -> 1280. Anchoring at 360
     meant the vw term was already below its own minimum at every phone width,
     so clamp() returned the floor on a 320px Android and on a 430px Pro Max
     alike — the scale existed but never moved across the range it was written
     for. 320 is where the smallest device in real use actually sits.

     Type moves LESS than spacing on purpose. Text below about 14px stops being
     comfortable regardless of screen, while padding can shed a third of itself
     and only look tighter — so the panels, gaps and bands do most of the work
     and the words stay readable. */
  --fs-micro:    clamp(11px,   .10vw + 10.67px, 12px);
  --fs-eyebrow:  clamp(10.5px, .21vw +  9.83px, 12.5px);
  --fs-small:    clamp(13.5px, .16vw + 13.00px, 15px);
  --fs-btn:      clamp(14px,   .21vw + 13.33px, 16px);
  --fs-body:     clamp(14px,   .31vw + 13.00px, 17px);
  --fs-sub:      clamp(14.5px, .26vw + 13.67px, 17px);
  --fs-card-h:   clamp(15.5px, .31vw + 14.50px, 18.5px);
  --fs-scenario: clamp(15px,   .26vw + 14.17px, 17.5px);

  --sp-1:  clamp(4px,    .21vw +  3.33px,  6px);
  --sp-2:  clamp(8px,    .31vw +  7.00px, 11px);
  --sp-3:  clamp(10px,   .52vw +  8.33px, 15px);
  --sp-4:  clamp(13px,   .73vw + 10.67px, 20px);
  --sp-5:  clamp(16px,  1.04vw + 12.67px, 26px);
  --sp-6:  clamp(22px,  1.67vw + 16.67px, 38px);
  --band-y:clamp(40px,  3.54vw + 28.67px, 74px);

  --tap:44px;
  --btn-x:clamp(16px,  .83vw + 13.33px, 24px);
  --btn-y:clamp(10.5px,.26vw +  9.67px, 13px);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--canvas);color:var(--text);font:16px/1.65 var(--font);
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;height:auto;display:block}
h1,h2,h3{line-height:1.12;letter-spacing:-.025em;margin:0 0 14px}
p{margin:0 0 14px}
a{color:inherit}

.wrap{max-width:1320px;margin:0 auto;padding:0 clamp(20px,4vw,56px)}
.wrap.narrow{max-width:820px}
.center{text-align:center}

.skip{position:absolute;left:-9999px;top:0;background:var(--black);color:var(--white);
  padding:12px 18px;z-index:100;border-radius:0 0 var(--r) 0}
.skip:focus{left:0}

/* ---- Buttons: the recurring brand signature ---------------------------- */
.tp-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:var(--btn-y) var(--btn-x);border-radius:var(--pill);font-weight:650;
  font-size:var(--fs-btn);min-height:var(--tap);
  line-height:1;text-decoration:none;border:1px solid transparent;cursor:pointer;
  position:relative;overflow:hidden;
  transition:background-color .15s ease,transform .06s ease,box-shadow .2s ease}
.tp-btn.sm{padding:calc(var(--btn-y) - 2px) calc(var(--btn-x) - 6px);
  font-size:var(--fs-small);min-height:38px}
.tp-btn:active{transform:translateY(1px)}
.tp-btn:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.tp-btn-primary{background:var(--gold);color:var(--black)}
.tp-btn-primary:hover{background:var(--gold-hi)}
.tp-btn-ghost-dark{background:transparent;color:var(--white);border-color:var(--line-dark)}
.tp-btn-ghost-dark:hover{background:rgba(237,237,237,.08)}

/* ---- Navigation: dark, because the logo is white + gold ---------------- */
.nav{background:var(--black);color:var(--white);position:sticky;top:0;z-index:50}
.nav-in{display:flex;align-items:center;gap:var(--sp-5);
  min-height:clamp(58px,6vw,72px);transition:min-height .25s ease}
.brand{flex:none;display:flex;align-items:center}
.brand img{height:clamp(26px,3.2vw,34px);width:auto;transition:height .25s ease}
.nav-links{display:flex;gap:var(--sp-5);margin-left:auto;font-size:var(--fs-small)}
.nav-links a{text-decoration:none;color:rgba(237,237,237,.82);padding:6px 0;border-bottom:2px solid transparent}
.nav-links a:hover{color:var(--white);border-bottom-color:var(--gold)}
.nav-actions{display:flex;gap:10px;flex:none}
.burger{display:none;background:none;border:0;padding:10px;cursor:pointer;margin-left:auto}
.burger span{display:block;width:22px;height:2px;background:var(--white);margin:4px 0;border-radius:2px}
.mobile{display:none;background:var(--black);border-top:1px solid var(--line-dark);
  padding:var(--sp-4) var(--sp-5) var(--sp-5)}
.mobile nav{display:flex;flex-direction:column;gap:2px}
.mobile nav a{color:var(--white);text-decoration:none;padding:13px 0;border-bottom:1px solid var(--line-dark)}
.mobile-actions{display:flex;flex-direction:column;gap:10px;margin-top:18px}
body.menu-open{overflow:hidden}

/* ---- Hero: dark, so the photography and the gold CTA carry the energy -- */
.hero{background:var(--black);color:var(--white);
  padding:calc(var(--band-y) * .86) 0 var(--band-y);position:relative;overflow:hidden}
/* BOTTOM-aligned, not centred. The copy column ends with the store buttons and
   the other column is the device, so aligning the ends puts the tablet's bottom
   border on the same line as the buttons' — the two things a reader's eye
   actually pairs. Centring left them on different lines by however much the two
   columns differed in height, which changed with every headline edit.

   `.hero-copy` has no rule of its own and `.stores` carries no bottom margin,
   so the column's bottom edge IS the buttons' bottom border. If either ever
   gains bottom spacing, this alignment silently gains the same gap. */
.hero-in{display:grid;grid-template-columns:1.05fr .95fr;gap:var(--sp-6);align-items:end;
  position:relative;z-index:1}
.eyebrow{text-transform:uppercase;letter-spacing:.13em;font-size:var(--fs-eyebrow);font-weight:600;
  color:var(--gold);margin:0 0 var(--sp-4)}
.hero h1{font-size:clamp(30px,5.4vw,62px);margin-bottom:var(--sp-4)}
.hero .hl{font-style:normal;border-bottom:4px solid var(--gold);padding-bottom:2px}
.lead{font-size:clamp(15.5px,1.7vw,20px);color:rgba(237,237,237,.78);max-width:38ch;
  margin-bottom:var(--sp-6)}
.actions{display:flex;gap:var(--sp-3);flex-wrap:wrap}
.actions.center{justify-content:center}
.hero-media img{border-radius:var(--r-lg);box-shadow:0 30px 60px -30px rgba(0,0,0,.7)}

/* ---- Bands ------------------------------------------------------------- */
.band{padding:var(--band-y) 0}
.band h2{font-size:clamp(23px,3.4vw,40px)}
.sub{color:var(--muted);max-width:60ch;margin-bottom:var(--sp-6);font-size:var(--fs-sub)}
.band.dark{background:var(--dark);color:var(--white)}
.band.dark .sub{color:rgba(237,237,237,.7)}
.band.final{background:var(--black);color:var(--white)}
.band.final .sub{color:rgba(237,237,237,.7)}
.band.apps{background:var(--gold-tint)}

/* ---- Cards ------------------------------------------------------------- */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,258px),1fr));gap:var(--sp-4)}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--sp-5);box-shadow:var(--shadow);position:relative;overflow:hidden}
.band.dark .card{background:rgba(237,237,237,.05);border-color:var(--line-dark);box-shadow:none}
.card h3{font-size:var(--fs-card-h);margin-bottom:var(--sp-2)}
.card p{color:var(--muted);font-size:var(--fs-small);margin:0}
.band.dark .card p{color:rgba(237,237,237,.72)}
.card-ic{width:clamp(36px,4vw,42px);height:clamp(36px,4vw,42px);border-radius:11px;
  display:grid;place-items:center;
  background:var(--gold-tint);color:#8A6520;margin-bottom:var(--sp-4)}
.band.dark .card-ic{background:rgba(223,179,87,.16);color:var(--gold)}
.ic{width:20px;height:20px}
.link{display:inline-block;margin-top:var(--sp-3);font-weight:600;font-size:var(--fs-small);
  text-decoration:none;border-bottom:2px solid var(--gold);padding-bottom:1px}
.badge{display:inline-block;font-size:var(--fs-micro);font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;background:var(--gold);color:var(--black);padding:3px var(--sp-2);
  border-radius:var(--pill);vertical-align:middle}

/* ---- Scenarios --------------------------------------------------------- */
.scenarios{list-style:none;padding:0;margin:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,262px),1fr));gap:var(--sp-4)}
.scenarios li{border-left:3px solid var(--gold);padding:4px 0 4px var(--sp-4);position:relative}
.scenarios p{margin:0;font-size:var(--fs-scenario);line-height:1.45}
.tag{display:block;font-size:var(--fs-micro);text-transform:uppercase;letter-spacing:.1em;
  color:var(--gold);font-weight:600;margin-bottom:6px}

/* ---- Steps ------------------------------------------------------------- */
.steps{list-style:none;padding:0;margin:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));gap:var(--sp-5);counter-reset:s}
.steps li{display:flex;gap:var(--sp-3);align-items:flex-start}
.step-n{flex:none;width:clamp(32px,3.6vw,38px);height:clamp(32px,3.6vw,38px);border-radius:50%;
  display:grid;place-items:center;position:relative;
  background:var(--black);color:var(--gold);font-weight:700;font-size:var(--fs-btn)}
.steps h3{font-size:var(--fs-card-h);margin-bottom:5px}
.steps p{color:var(--muted);font-size:var(--fs-small);margin:0}

/* ---- Ticks, areas, shots ---------------------------------------------- */
.ticks{list-style:none;padding:0;margin:0 0 var(--sp-5);display:grid;gap:var(--sp-2)}
.ticks li{display:flex;gap:var(--sp-2);align-items:flex-start;font-size:var(--fs-body)}
.ticks .ic{flex:none;margin-top:3px;color:var(--gold)}
.earn-in{display:grid;grid-template-columns:1.05fr .95fr;gap:var(--sp-6);align-items:center}
.earn-media img{border-radius:var(--r-lg)}
.areas{list-style:none;padding:0;margin:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,178px),1fr));gap:var(--sp-3)}
.areas li{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--sp-3) var(--sp-4)}
.areas strong{display:block;font-size:var(--fs-sub)}
.areas span{display:block;color:var(--muted);font-size:var(--fs-small)}
.areas em{font-style:normal;font-size:var(--fs-micro);font-weight:700;text-transform:uppercase;
  letter-spacing:.06em}
.areas .live em{color:#2E7D32}
.areas .soon em{color:var(--muted)}
.shots{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:24px}
.shots figure{margin:0}
.shots img{border-radius:var(--r-lg);box-shadow:var(--shadow)}
.shots figcaption{margin-top:var(--sp-3);font-size:var(--fs-small);color:var(--muted)}

/* ---- FAQ: <details>, so it works with no JavaScript -------------------- */
.faq{border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{cursor:pointer;padding:var(--sp-4) var(--sp-6) var(--sp-4) 0;font-weight:600;
  font-size:var(--fs-sub);min-height:var(--tap);
  list-style:none;position:relative}
.faq summary::-webkit-details-marker{display:none}
/* Centred rather than pinned at a fixed 27px from the top. That offset was
   only ever correct at the old fixed padding; with fluid padding the chevron
   drifted off the text on small screens. `translateY(-50%)` has to be carried
   through both rotate states or the marker jumps when it opens. */
.faq summary::after{content:'';position:absolute;right:8px;top:50%;width:9px;height:9px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:translateY(-60%) rotate(45deg);transition:transform .18s ease}
.faq details[open] summary::after{transform:translateY(-30%) rotate(-135deg)}
.faq summary:focus-visible{outline:2px solid var(--gold);outline-offset:2px;border-radius:4px}
.answer{padding:0 var(--sp-6) var(--sp-5) 0;color:var(--muted);font-size:var(--fs-body)}
.answer p:last-child{margin-bottom:0}

/* ---- Store buttons ----------------------------------------------------- */
.stores{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:26px}
.store{display:inline-flex;align-items:center;gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-4);min-height:var(--tap);border-radius:12px;
  background:var(--black);color:var(--white);text-decoration:none;min-width:196px;
  border:1px solid transparent;transition:border-color .15s ease,background-color .15s ease}
.store small{display:block;font-size:var(--fs-micro);opacity:.7;text-transform:uppercase;letter-spacing:.06em}
.store strong{font-size:var(--fs-small)}
.store.soon{opacity:.45;pointer-events:none}
.store:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
/* The marks are two different shapes at two different scales — the Apple logo
   is optically smaller at the same box size, so it gets its own height. */
.store-ic{flex:none;width:22px;height:22px}
.store .store-ic[viewBox^="0 0 384"]{width:19px;height:23px}

/* On the dark hero a black button on a black band is an invisible button, so
   there it is outlined rather than filled. */
.hero .stores{justify-content:flex-start;margin-top:30px}
.hero .store{border-color:rgba(237,237,237,.30);background:rgba(237,237,237,.04)}
.hero .store:hover{border-color:rgba(237,237,237,.55);background:rgba(237,237,237,.09)}

/* ---- Footer ------------------------------------------------------------ */
.foot{background:var(--black);color:rgba(237,237,237,.72);
  padding:calc(var(--band-y) * .78) 0 0;font-size:var(--fs-small)}
.foot-in{display:grid;grid-template-columns:1fr 2fr;gap:48px;padding-bottom:40px}
.foot-brand img{height:88px;width:auto;margin-bottom:14px}
.foot-brand p{max-width:34ch;font-size:var(--fs-small)}
.foot-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:28px}
.foot-cols h3{color:var(--white);font-size:var(--fs-micro);text-transform:uppercase;
  letter-spacing:.1em;margin-bottom:var(--sp-3)}
.foot-cols a{display:block;text-decoration:none;padding:5px 0;color:rgba(237,237,237,.72)}
.foot-cols a:hover{color:var(--gold)}
.foot-legal{border-top:1px solid var(--line-dark);padding-top:var(--sp-4);
  padding-bottom:var(--sp-5);font-size:var(--fs-small)}
.foot-legal p{margin:0}

/* ---- Mobile: the primary layout, not an afterthought ------------------- */
@media (max-width:900px){
  .nav-links,.nav-actions{display:none}
  .burger{display:block}
  /* :not([hidden]) matters. A bare `.mobile{display:block}` outranks the UA
     stylesheet's [hidden]{display:none}, which left the menu permanently open
     above the hero on every phone — the burger toggled an attribute that CSS
     was already overriding. */
  .mobile:not([hidden]){display:block}
  .hero-in,.earn-in{grid-template-columns:1fr;gap:var(--sp-6)}
  /* On a phone the carousel leads: the product first, then the copy, then the
     way to get it. (The old rule here named .hero-media, a class the tablet
     frame replaced — it had been ordering nothing for two commits.) */
  .hero .tablet{order:-1}
  .foot-in{grid-template-columns:1fr;gap:var(--sp-6)}
  /* Side by side while there is room for it. This used to be `flex:1 1 100%`,
     which stacked the CTAs into two full-width slabs at every width below 900px
     — including a 760px tablet, where a button the width of the page reads as a
     mistake rather than as emphasis. */
  .actions .tp-btn,.stores .store{flex:1 1 auto}
}

/* Below this the two CTAs genuinely do not fit side by side, so they stack and
   take the full width — which on a phone is the right shape for a thumb. */
@media (max-width:560px){
  .actions .tp-btn,.stores .store{flex:1 1 100%}
}

/* The smallest phones still in real use (320-380px). Nothing here changes the
   design; it only stops the trim from running out. */
@media (max-width:380px){
  .wrap{padding:0 16px}
  .nav-in{gap:12px}
  /* At this width a two-word nav label and the logo compete for the same row. */
  .brand img{height:24px}
  .slides{scroll-padding:0}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}


/* ---- Hero carousel in a tablet -----------------------------------------
   CSS scroll-snap, no script. It swipes natively on touch, scrolls with the
   keyboard, and honours prefers-reduced-motion for free. A JS carousel would
   be the largest script on an otherwise script-free page, to do worse what
   the browser already does. */

.tablet{
  position:relative;
  /* The bezel. Slightly lighter than the hero background so the device reads
     as an object on the page rather than a hole cut into it. */
  background:linear-gradient(160deg,#1C1C1C,#0C0C0C);
  /* A hairline of gold, at about a third strength. Full #DFB357 at 1px reads as
     a drawn outline and starts competing with the CTA for the eye; muted, it
     only separates the device from the black behind it — which is the whole job.
     Gold is jewellery, not wallpaper, and a border is the largest continuous
     run of it on the page. */
  border:1px solid rgba(223,179,87,.34);
  border-radius:clamp(18px,2.4vw,26px);
  padding:clamp(9px,1.2vw,14px);
  /* The inset highlight becomes a warm one so the top edge catches the same
     light as the border rather than reading as a separate white rim. */
  box-shadow:
    0 40px 80px -40px rgba(0,0,0,.85),
    0 0 0 1px rgba(223,179,87,.06),
    inset 0 1px 0 rgba(223,179,87,.14);
}
.tablet:focus-visible{outline:2px solid var(--gold);outline-offset:4px}
/* position:relative so the arrows centre on the SCREEN. Against .tablet they
   would sit half a dots-row too low. */
/* The screen gets the faintest gold rim too, so the bezel and the picture read
   as one object rather than a frame with an unrelated hole in it. */
.tablet-screen{
  position:relative;border-radius:16px;overflow:hidden;background:#080808;aspect-ratio:4/3;
  border:1px solid rgba(223,179,87,.12);
}

.slides{
  display:flex;margin:0;padding:0;list-style:none;height:100%;
  overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;-ms-overflow-style:none;
}
.slides::-webkit-scrollbar{display:none}
.slide{position:relative;flex:0 0 100%;scroll-snap-align:center;height:100%}
.slide img{width:100%;height:100%;object-fit:cover}

/* A slide with no photograph yet: a warm tinted panel, not a broken frame. */
.slide-placeholder{
  width:100%;height:100%;
  background:
    radial-gradient(120% 90% at 20% 15%, rgba(223,179,87,.20), transparent 60%),
    linear-gradient(150deg,#1A1A1A,#0E0E0E);
}

/* Caption sits ON the image, over a gradient so it stays legible whatever the
   photograph does underneath it. */
.slide-cap{
  position:absolute;left:0;right:0;bottom:0;
  padding:clamp(30px,4vw,44px) clamp(14px,2vw,22px) clamp(12px,1.6vw,18px);
  /* Gold, bold. This is the accent's other safe home: on a near-black ground
     #DFB357 is about 9:1, where the same colour on the sand canvas is 1.9:1 and
     unreadable. The gradient below is what guarantees that ground whatever the
     photograph does underneath.
     A text-shadow, not a heavier gradient — the caption has to stay legible
     over a bright patch of sky without darkening the picture any further. */
  color:var(--gold);font-size:clamp(13.5px,1.2vw,16px);font-weight:700;line-height:1.35;
  letter-spacing:.005em;
  text-shadow:0 1px 3px rgba(0,0,0,.55);
  background:linear-gradient(to top,rgba(10,10,10,.92),rgba(10,10,10,.58) 55%,transparent);
}

/* Prev/next. Positioned over the slide, Owl-style, and revealed by the script —
   they are inert without it, so `hidden` stays until JS takes over. The
   attribute needs an explicit rule because `display:grid` beats the UA's
   [hidden]{display:none}. */
.tp-arrow{
  position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:clamp(36px,4vw,42px);height:clamp(36px,4vw,42px);padding:0;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  color:var(--white);
  border:1px solid rgba(237,237,237,.22);
  background:rgba(10,10,10,.55);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background .2s ease,border-color .2s ease,opacity .2s ease;
}
.tp-arrow[hidden]{display:none}
.tp-arrow svg{width:17px;height:17px;display:block}
.tp-arrow:hover{background:rgba(10,10,10,.82);border-color:rgba(223,179,87,.65)}
.tp-arrow:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.tp-arrow.prev{left:10px}
.tp-arrow.next{right:10px}
/* Touch devices swipe; the arrows would just cover the photograph. */
@media (hover:none){ .tp-arrow{display:none} }

.dots{display:flex;gap:var(--sp-2);justify-content:center;padding:var(--sp-3) 0 4px}
/* The visible dash is 4px tall; the ANCHOR is 30px, so the thing a thumb has
   to hit is not the thing the eye sees. Padding, not size, does the work. */
.dots a{width:30px;height:30px;display:grid;place-items:center;border-radius:var(--pill)}
.dots span{display:block;width:100%;height:4px;border-radius:var(--pill);background:rgba(237,237,237,.28);transition:background .25s ease}
.dots a:hover span{background:rgba(237,237,237,.55)}
.dots a:focus-visible{outline:2px solid var(--gold);outline-offset:2px}

/* The active dot. The script keeps aria-current on the slide actually in view,
   so the indicator follows a swipe and autoplay, not just a click.
   (This replaces a `.slide:target ~ .dots` rule that could never match — .dots
   is not a sibling of .slide — and that painted the inactive grey anyway.) */
.dots a[aria-current="true"] span{background:var(--gold)}

/* Scriptless fallback: clicking a dot sets :target, and :has() reaches back up
   to the carousel to light the matching control. Capped at six, like the
   stagger below — past that the CMS is using the hero as a gallery. */
.tablet:has(#slide-1:target) .dots a[href="#slide-1"] span,
.tablet:has(#slide-2:target) .dots a[href="#slide-2"] span,
.tablet:has(#slide-3:target) .dots a[href="#slide-3"] span,
.tablet:has(#slide-4:target) .dots a[href="#slide-4"] span,
.tablet:has(#slide-5:target) .dots a[href="#slide-5"] span,
.tablet:has(#slide-6:target) .dots a[href="#slide-6"] span{background:var(--gold)}

/* The hero splits 50/50 once there is a device to show; without one the copy
   gets the full width rather than a lonely half. */
.hero-in{grid-template-columns:1fr 1fr;gap:var(--sp-6)}
.hero-in.solo{grid-template-columns:1fr;max-width:820px}

@media (max-width:900px){
  .tablet-screen{border-radius:12px;aspect-ratio:3/2}
  /* One column: there is nothing to align across, and the device leads. */
  .hero-in{grid-template-columns:1fr;align-items:stretch}
}
/* The device gets shallower on a phone, where 4:3 would eat the fold. */
@media (max-width:560px){
  .tablet-screen{aspect-ratio:5/4}
}

/* ---- Motion -------------------------------------------------------------
   Everything here is a PROGRESSIVE ENHANCEMENT behind `.js`, added by the
   script only when the visitor has not asked for reduced motion. If the script
   never runs, nothing was ever hidden and the page is complete — which is the
   failure mode of every animate-on-scroll library that sets opacity:0 in the
   stylesheet and leaves a blank page when its bundle 404s.

   The vocabulary is deliberately small and consistent: things arrive from
   slightly below, gold draws itself in, and nothing ever bounces, spins or
   overshoots. Each effect fires ONCE. A page whose decoration keeps moving
   after you have arrived reads as a demo; one that settles and stops reads as
   a product. Every duration below is between .4s and .9s — long enough to be
   perceived as motion rather than a flicker, short enough that nobody waiting
   to read is kept waiting. */

.js [data-rise] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .6s cubic-bezier(.22,.61,.36,1), transform .6s cubic-bezier(.22,.61,.36,1);
  will-change: opacity, transform;
}
.js [data-rise].in { opacity: 1; transform: none; }

/* ---- Groups stagger their CHILDREN --------------------------------------
   This block previously set `transition-delay` on the children of a group and
   nothing else. Children had no transition and no hidden state of their own —
   only the container did — so the delays applied to a property that was never
   animating and every "staggered" row actually arrived as one flat fade. The
   delays below now have something to delay.

   The container stops hiding itself when it is also a group, or the row would
   fade in as a block and then its cards would fade in again inside it. */
.js [data-rise][data-rise-group] { opacity: 1; transform: none; }
.js [data-rise-group] > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1), transform .55s cubic-bezier(.22,.61,.36,1);
  transition-delay: 0ms;
}
.js [data-rise-group].in > * { opacity: 1; transform: none; }
.js [data-rise-group].in > *:nth-child(2) { transition-delay: 70ms; }
.js [data-rise-group].in > *:nth-child(3) { transition-delay: 140ms; }
.js [data-rise-group].in > *:nth-child(4) { transition-delay: 210ms; }
.js [data-rise-group].in > *:nth-child(5) { transition-delay: 280ms; }
.js [data-rise-group].in > *:nth-child(6) { transition-delay: 350ms; }

/* The hero is above the fold — it should not fade in on load, it should be
   there. Only its own arrival is animated, and only slightly. */
.js .hero [data-rise] { transform: translateY(10px); transition-duration: .45s; }

/* ---- The gold rule under each section heading ---------------------------
   A 44px hairline that draws itself from the left as the heading arrives. This
   is the page's one repeating graphical gesture: it marks the start of a
   section the way a printed rule does, and because it DRAWS rather than fades,
   it reads as deliberate rather than as a decoration that happened to be
   there. Placed on ::after so no section markup changes. */
.band h2 { position: relative; padding-bottom: 13px; margin-bottom: 5px; }
.band h2::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 44px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold), rgba(223,179,87,.25));
  transform-origin: left center;
}
.js .band h2[data-rise]::after { transform: scaleX(0); }
.js .band h2[data-rise].in::after {
  transform: scaleX(1);
  transition: transform .7s cubic-bezier(.22,.61,.36,1) .12s;
}
/* Centred headings get a centred rule, or it hangs off the left of a line of
   text that is nowhere near the left edge. `.center` sits on the wrap, so the
   heading is its child. */
.center h2::after { left: 50%; transform: translateX(-50%); transform-origin: center; }
.js .center h2[data-rise]::after    { transform: translateX(-50%) scaleX(0); }
.js .center h2[data-rise].in::after { transform: translateX(-50%) scaleX(1); }

/* On the gold-tinted apps band, #DFB357 on #F5E9CD is barely a change of shade.
   The same gesture in a darker gold keeps the rule visible without introducing
   a second accent colour. */
.band.apps h2::after { background: linear-gradient(90deg, #B08324, rgba(176,131,36,.25)); }

/* ---- Cards: a gold edge that arrives with them --------------------------
   The card already rises. This adds a hairline along its top edge that sweeps
   in behind it, so a grid of cards resolves into a row of objects rather than
   four rectangles fading up together. It is the same gesture as the heading
   rule, at a different scale — which is what makes the page feel authored
   rather than assembled from effects. */
.card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, var(--gold), rgba(223,179,87,0));
  transform-origin: left center;
}
.js [data-rise-group] .card::before { transform: scaleX(0); }
.js [data-rise-group].in .card::before {
  transform: scaleX(1);
  transition: transform .8s cubic-bezier(.22,.61,.36,1) .18s;
}

/* ---- Scenarios: the gold spine draws downward ---------------------------
   These are already marked by a gold left border. Animating the border itself
   is not possible, so the border goes transparent and an absolutely positioned
   bar draws in its place — vertically, because the eye reads a list downward
   and the motion should agree with it. */
.js .scenarios[data-rise-group] li { border-left-color: transparent; }
.scenarios li::before {
  content: ""; position: absolute; left: -3px; top: 0; bottom: 0; width: 3px;
  background: var(--gold); transform-origin: top center;
}
.js .scenarios[data-rise-group] li::before { transform: scaleY(0); }
.js .scenarios[data-rise-group].in li::before {
  transform: scaleY(1);
  transition: transform .65s cubic-bezier(.22,.61,.36,1) .1s;
}

/* ---- Steps: one ring, once ----------------------------------------------
   A single expanding ring leaving each numbered circle as it arrives. It fires
   ONCE and never repeats — a looping pulse is the exact effect that makes a
   page look like a template, and it would also keep a compositor layer awake
   for the whole visit. The stagger is inherited from the group, so the rings
   go off in step order, which is the one thing this section is about. */
.step-n::after {
  content: ""; position: absolute; inset: -6px; border-radius: 50%;
  border: 1px solid var(--gold); opacity: 0;
}
.js .steps[data-rise-group].in .step-n::after {
  animation: tp-ring .9s cubic-bezier(.22,.61,.36,1) forwards;
}
.js .steps[data-rise-group].in li:nth-child(2) .step-n::after { animation-delay: 70ms; }
.js .steps[data-rise-group].in li:nth-child(3) .step-n::after { animation-delay: 140ms; }
.js .steps[data-rise-group].in li:nth-child(4) .step-n::after { animation-delay: 210ms; }
.js .steps[data-rise-group].in li:nth-child(5) .step-n::after { animation-delay: 280ms; }
.js .steps[data-rise-group].in li:nth-child(6) .step-n::after { animation-delay: 350ms; }
@keyframes tp-ring {
  0%   { opacity: .85; transform: scale(.82); }
  100% { opacity: 0;   transform: scale(1.35); }
}

/* ---- Coverage tiles: settle rather than slide --------------------------- */
.js .areas[data-rise-group] > li {
  transform: translateY(14px) scale(.985);
  transition: opacity .5s cubic-bezier(.22,.61,.36,1), transform .5s cubic-bezier(.22,.61,.36,1);
}
.js .areas[data-rise-group].in > li { transform: none; }

/* ---- The hero's ambient light -------------------------------------------
   A single wide gold wash behind the hero, drifting slowly enough that it is
   never the thing you are looking at — it just stops a large black rectangle
   from being flat. CSS-only, one element, no script.

   Kept at very low alpha on purpose. Gold is jewellery on this page; a visible
   gold haze would be the largest continuous run of it anywhere and would fight
   the CTA for the eye, which is the one thing the palette exists to prevent. */
.hero::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  top: -30%; left: 50%; width: min(1100px, 130%); aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(223,179,87,.13), rgba(223,179,87,.04) 55%, transparent 72%);
}
.js .hero::before { animation: tp-drift 26s ease-in-out infinite alternate; }
@keyframes tp-drift {
  from { transform: translate(-52%, -2%) scale(1);    opacity: .85; }
  to   { transform: translate(-48%,  3%) scale(1.08); opacity: 1; }
}

/* ---- The device settles into place --------------------------------------
   The tablet arrives a touch later and a touch further than the copy beside
   it, so the hero resolves as copy-then-product rather than as one block. */
.js .hero .tablet[data-rise] { transform: translateY(16px) scale(.986); transition-duration: .7s; }
.js .hero .tablet[data-rise].in { transform: none; }

/* ---- The carousel's active slide ----------------------------------------
   A very slow push-in on whichever photograph is showing, and a caption that
   rises as it becomes the active one. Both are keyed off `.is-active`, set by
   the same script that already tracks the index — so the effect cannot drift
   out of sync with what is on screen.

   1.06 over eight seconds is roughly a pixel a second on a phone: felt, not
   watched. Anything faster becomes a zoom, and a zooming photograph is the
   single most dated effect on the web.

   A TRANSITION rather than a keyframe animation, deliberately. A keyframe with
   `forwards` holds the image at 1.06 and then drops it the instant the slide
   stops being active — which is a visible snap on the neighbouring slide while
   a finger is mid-swipe and two slides are on screen at once. A transition
   eases both ways, so the outgoing photograph relaxes back over the same eight
   seconds and nobody ever sees it move. */
.js .slide img { transition: transform 8s ease-out; }
.js .slide.is-active img { transform: scale(1.06); }

.js .slide.is-active .slide-cap { animation: tp-cap .5s cubic-bezier(.22,.61,.36,1) both; }
@keyframes tp-cap {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}

/* ---- The nav condenses once you leave the top ---------------------------
   Shorter, and a gold hairline appears along the bottom edge — so the bar
   reads as a layer over the page rather than as part of the hero it was
   originally sitting inside. Toggled by script; without it the nav is simply
   always in its full state. */
.nav { transition: box-shadow .3s ease, background-color .3s ease; }
.nav.condensed { box-shadow: 0 1px 0 rgba(223,179,87,.28), 0 10px 30px -22px rgba(0,0,0,.9); }
.nav.condensed .nav-in { min-height: clamp(50px, 4.6vw, 58px); }
.nav.condensed .brand img { height: clamp(23px, 2.7vw, 29px); }

/* ---- Buttons: a sheen, on hover only ------------------------------------
   A band of light crossing the gold fill. It is the one flourish on the page
   that exists purely to feel expensive, so it is spent on the single element
   the whole page is asking you to press, and nowhere else. Hover-only, so it
   never fires unprompted on a phone. */
.tp-btn-primary::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.42) 50%, transparent 62%);
  transform: translateX(-120%);
  pointer-events: none;
}
@media (hover: hover) {
  .tp-btn-primary:hover::after { transition: transform .65s ease; transform: translateX(120%); }
  .tp-btn-primary:hover { box-shadow: 0 8px 22px -12px rgba(223,179,87,.8); }
}

/* Cards and the tablet lift very slightly on hover. Subtle enough to feel
   responsive, not enough to shift the layout. */
.card, .tablet, .areas li { transition: transform .18s ease, box-shadow .18s ease; }
@media (hover: hover) {
  .card:hover, .areas li:hover { transform: translateY(-2px); }
  .tablet:hover { transform: translateY(-3px); }
  .card:hover { box-shadow: 0 22px 46px -30px rgba(23,23,23,.6); }
}

@media (prefers-reduced-motion: reduce) {
  /* Not "faster" — OFF. Everything is visible, in place, and still. The script
     also refuses to add `.js` at all in this case, so most of the above never
     arms; these rules cover the parts that are not behind it. */
  .js [data-rise], .js [data-rise-group] > * {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .card::before, .band h2::after, .scenarios li::before { transform: none !important; transition: none !important; }
  .scenarios li { border-left-color: var(--gold) !important; }
  .step-n::after, .hero::before, .slide.is-active .slide-cap { animation: none !important; }
  .slide img, .slide.is-active img { transition: none !important; transform: none !important; }
  .step-n::after { opacity: 0 !important; }
  .card:hover, .tablet:hover, .areas li:hover { transform: none; }
  .tp-btn-primary::after { display: none; }
}

/* The action that works today, sitting under the pending store buttons. */
.web-cta{margin-top:var(--sp-5)}
.web-note{margin:var(--sp-3) 0 0;font-size:var(--fs-small);color:var(--muted)}
