/* ============================================================
   AUDIBLE GOODS — marketing site

   Everything structural comes from tokens.css. This file only adds
   the handful of arrangements the site needs on top of the system:
   a masthead, a hero, the product screens, and a footer.

   If a rule here starts redefining colour or type, it belongs in
   tokens.css instead.

   The home page reads a screen at a time. Two mechanisms do that, and
   they are deliberately independent:

     SNAP     is pure CSS — scroll-snap on the document scroller. It is
              switched off below 761px wide or 640px tall, because a
              mandatory snap point in front of a section too tall for the
              viewport makes the bottom of that section unreachable.
              Off, the page is an ordinary document; nothing else changes.

     SETTLE   is the lag. motion.js writes one value, --lag, and anything
              carrying data-depth is displaced by lag x depth, so the
              artwork trails further than the type and lands after it.
              With scripting off --lag never exists and every transform
              resolves to zero.
   ============================================================ */

@import url("./tokens.css");

/* ============================================================
   FULL-PAGE SCROLL
   ============================================================ */

html{scroll-behavior:smooth}

/* The masthead is fixed, so every screen reserves its height. motion.js
   measures the real thing and overwrites this; the value here is the
   one-row desktop height and only has to hold until scripts run. */
:root{--mast-h:65px}

/* The width here is not a taste call: it is the same 900px at which the
   showcase drops to one column. Stacked, a product screen is ~950px tall,
   and a mandatory snap point in front of a section taller than the
   viewport makes the bottom of that section unreachable — you release the
   wheel and it snaps back to the top of the screen you were trying to
   read past. Measured at 820x900: Saturn 945px, Polychrome 990px. So
   full-page scroll is on exactly where the two-column layout holds, and
   the query below must move if that breakpoint ever does. */
@media (min-width:901px) and (min-height:680px){
  /* scroll-behavior:auto is not a preference here, it is load-bearing.
     A mandatory snap container and a smooth programmatic scroll fight:
     an in-page jump either aborts and returns to where it started, or
     runs its animation and stops ~130px short of the snap point, which
     leaves the heading under the masthead and never re-snaps. Measured
     in this engine, both ways. Handing the animation entirely to snap
     fixes it — the jump is instant and the settle below plays the
     content in, which is a better arrival than a scroll tween anyway.

     It is scoped to exactly the query that turns snapping on, so the
     two cannot drift apart: wherever the page is an ordinary document
     the smooth scroll above still applies. */
  html.js[data-page="home"]{scroll-snap-type:y mandatory;scroll-behavior:auto}
  html.js[data-page="home"] .snap{scroll-snap-align:start;scroll-snap-stop:always}
}

.snap{
  position:relative;
  min-height:100vh;
  min-height:100svh;
  display:flex;flex-direction:column;justify-content:center;
  padding-block:calc(var(--mast-h) + var(--sp-7)) var(--sp-7);
}
/* The hairline between screens is the datasheet rule the old page used
   between sections. At a snap point it sits under the masthead and is
   invisible; it is there for the travel in between, and for every
   viewport where snapping is switched off. */
.snap + .snap{border-top:var(--ag-hair) solid var(--ag-rule)}

/* A zero-size target so an old ../#products link still lands somewhere
   sensible now that the two products no longer share a section. */
.anchor-alias{position:absolute;top:0;left:0;width:0;height:0;
  scroll-margin-top:var(--mast-h)}

/* ---------- the settle ------------------------------------------------

   ONE transform, driven by --lag, and it is the only thing allowed to
   write `transform` on these elements. The reveal underneath uses the
   independent `translate` property precisely so the two compose instead
   of overwriting each other — swapping either one for the other breaks
   both. --depth and --d are stamped on by motion.js from the single
   data-depth attribute in the markup. */

[data-depth]{
  transform:translate3d(0,calc(var(--lag,0px) * var(--depth,0)),0);
}
.showcase-art{will-change:transform}

html.js .reveal [data-depth]{
  translate:0 22px;opacity:0;
  transition:translate var(--ag-settle) var(--ag-ease) var(--d,0ms),
             opacity   var(--ag-settle) var(--ag-ease) var(--d,0ms);
}
html.js .reveal.is-in [data-depth]{translate:0 0;opacity:1}

/* Reduced motion takes all of it: no snap, no lag, no reveal. The
   selectors match the ones above rather than out-weighing them, so
   source order does the work. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  html.js[data-page="home"]{scroll-snap-type:none}
  [data-depth]{transform:none}
  html.js .reveal [data-depth]{translate:0 0;opacity:1;transition:none}
}

/* ---------- skip link ------------------------------------------------ */

.skip{
  position:absolute;left:-9999px;top:0;z-index:20;
  font-family:var(--ag-label);font-size:var(--t-label);letter-spacing:.14em;
  text-transform:uppercase;text-decoration:none;
  background:var(--ag-fg);color:var(--ag-on-fg);padding:12px 18px;
}
.skip:focus{left:var(--sp-4);top:var(--sp-4)}

/* ---------- masthead ------------------------------------------------- */

/* Fixed, because with a snapping page there is no top of the document to
   scroll back to. Transparent over the first screen and picking up its
   ground once the page has moved — motion.js toggles .is-scrolled. */
.masthead{
  position:fixed;inset-inline:0;top:0;z-index:10;
  border-bottom:var(--ag-hair) solid transparent;
  transition:background var(--ag-slow) var(--ag-ease),
             border-color var(--ag-slow) var(--ag-ease);
}
.masthead.is-scrolled{background:var(--ag-bg);border-bottom-color:var(--ag-rule)}
/* Product pages are ordinary documents that begin under the masthead. */
html:not(.js) .masthead,body:not(.home) .masthead{background:var(--ag-bg);
  border-bottom-color:var(--ag-rule)}
body:not(.home) #main{padding-top:calc(var(--mast-h) + var(--sp-6))}

.masthead .ag-wrap{
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-5);padding-block:var(--sp-4);flex-wrap:wrap;
}
.brand-link{display:inline-flex;text-decoration:none;line-height:0}
/* 32px, not 28: at 28 the lockup lands at 114.5px wide, which is exactly the
   mark's minimum and leaves no headroom. 32px puts it at 131px. */
.brand-link img{height:32px;width:auto}

.nav{display:flex;align-items:center;gap:var(--sp-5);flex-wrap:wrap}
.nav a{
  font-family:var(--ag-label);font-size:var(--t-label);font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;text-indent:.14em;
  text-decoration:none;color:var(--ag-fg-muted);
  transition:color var(--ag-fast) var(--ag-ease);
}
.nav a:hover{color:var(--ag-fg)}

/* Three-state, because "auto" is a real setting and not the absence of
   one — the products are a dark machine and a light machine, and some
   people will want to pin the site to one regardless of their OS. */
.theme-toggle{
  font-family:var(--ag-label);font-size:var(--t-micro);font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;text-indent:.14em;
  background:transparent;color:var(--ag-fg-muted);cursor:pointer;
  border:var(--ag-hair) solid var(--ag-rule);border-radius:var(--ag-radius-1);
  padding:7px 11px;min-width:72px;
  transition:color var(--ag-fast) var(--ag-ease),
             border-color var(--ag-fast) var(--ag-ease);
}
.theme-toggle:hover{color:var(--ag-fg);border-color:var(--ag-rule-strong)}
/* No JS, no toggle — the page still follows the OS correctly. */
html:not(.js) .theme-toggle{display:none}

/* ---------- the section rail ------------------------------------------

   A page that moves a screen at a time has to say where you are and how
   much is left. Engraved ticks rather than dots, and the label only when
   you are on it or pointing at it, so the rail stays a margin note. */

.rail{
  position:fixed;z-index:9;
  right:max(var(--sp-5),env(safe-area-inset-right));
  top:50%;margin-top:0;translate:0 -50%;
  display:flex;flex-direction:column;align-items:flex-end;gap:var(--sp-4);
}
.rail a{
  display:flex;flex-direction:row-reverse;align-items:center;gap:var(--sp-3);
  text-decoration:none;color:var(--ag-fg-faint);
  transition:color var(--ag-fast) var(--ag-ease);
}
.rail a:hover,.rail a[aria-current]{color:var(--ag-fg)}
.rail-tick{
  display:block;width:16px;height:var(--ag-hair);background:currentColor;
  transition:width var(--ag-slow) var(--ag-ease);
}
.rail a[aria-current] .rail-tick{width:34px}
.rail-name{
  font-family:var(--ag-label);font-size:var(--t-micro);font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
  opacity:0;translate:8px 0;
  transition:opacity var(--ag-slow) var(--ag-ease),
             translate var(--ag-slow) var(--ag-ease);
}
.rail a:hover .rail-name,
.rail a:focus-visible .rail-name,
.rail a[aria-current] .rail-name{opacity:1;translate:0 0}
/* Two reasons to drop it, and they need different widths. Below 1080px
   the rail would sit on top of the content; below the snap query there
   are no screens for it to index at all. The height here is the inverse
   of the snap query's and has to move with it. */
@media (max-width:1080px),(max-height:679px){.rail{display:none}}

/* ---------- hero ----------------------------------------------------- */

/* One column. The mark used to sit on the right, which squeezed the plate
   to a width that broke the headline over three lines; the headline is the
   hero, so the mark gave way rather than the type. */
.hero-grid{display:grid;gap:var(--sp-8);width:100%}
/* The headline sits in the plate — the mark's old black field, borrowed
   back as a container. It inverts with the theme like every other plate:
   a black rectangle on paper, a paper one on ink, because a black panel
   on the dark ground would not be a panel at all. */
.hero .hero-plate{
  margin-block:var(--sp-4);padding:var(--sp-5) var(--sp-6);
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-7);
}
/* Held to a measure that breaks the line in two and balances the halves.
   The measure is in ch, so it tracks the size down and the break holds. */
.hero .hero-plate .ag-display{
  margin:0;max-width:17ch;text-wrap:balance;
  font-size:calc(var(--t-display) * .8);
}
/* Sizing only — never `display`, which would out-specify .only-light /
   .only-dark and un-hide the wrong artwork. See the note further down. */
.hero-plate-mark{flex:0 0 auto}
.hero-plate-mark img{width:100%;max-width:160px;height:auto}
.hero-cta{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin-top:var(--sp-6)}

.scroll-hint{
  position:absolute;left:50%;bottom:var(--sp-6);translate:-50% 0;
  display:inline-flex;flex-direction:column;align-items:center;gap:var(--sp-3);
  font-family:var(--ag-label);font-size:var(--t-micro);font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;text-indent:.16em;
  color:var(--ag-fg-faint);text-decoration:none;
  transition:color var(--ag-fast) var(--ag-ease);
}
.scroll-hint:hover{color:var(--ag-fg)}
.scroll-hint-rule{
  display:block;position:relative;overflow:hidden;
  width:var(--ag-hair);height:36px;background:var(--ag-rule-strong);
}
.scroll-hint-rule::after{
  content:"";position:absolute;inset-inline:0;height:14px;
  background:currentColor;animation:hint 2.1s var(--ag-ease) infinite;
}
@keyframes hint{0%{top:-14px}55%,100%{top:36px}}
/* The hint promises that one flick moves one screen, so it may only
   appear where that is true. This is the exact inverse of the snap query
   above; the two move together. */
@media (max-width:900px),(max-height:679px),(prefers-reduced-motion:reduce){
  .scroll-hint{display:none}
}

@media (max-width:820px){
  .hero-grid{gap:var(--sp-6)}
  /* No room beside the headline at this width; the mark is decorative and
     the page already carries it in the masthead. */
  .hero-plate-mark{display:none}
}

/* ============================================================
   PRODUCT SCREENS

   Saturn is the flagship and gets the larger of the two scales; the
   pair used to sit side by side in one grid, which read as a matched
   set. They are a sequence now, one screen each, artwork alternating
   sides so the second is recognisably the same object seen again
   rather than a comparison against the first.
   ============================================================ */

.showcase{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--sp-6) var(--sp-8);align-items:center;width:100%;
}
.showcase--lead{grid-template-columns:minmax(0,1fr) minmax(0,1.08fr)}
.showcase--flip .showcase-art{order:-1}

/* Polychrome is an upright unit and Saturn is a wide one, so they cannot
   share a column split. Given half the row a 0.61-aspect device caps out on
   height long before it uses the width, and sits in a lake of its own
   whitespace while the copy beside it is squeezed for no reason. The tall
   variant hands that width back to the copy and lets the device run taller
   instead. */
.showcase--tall{grid-template-columns:minmax(0,.54fr) minmax(0,1.46fr)}
/* Sized against Saturn rather than against its own column: an upright device
   allowed the same height as a wide one is half again as big on the page and
   reads as the more important of the two, which is backwards. No margin-inline
   here on purpose — .showcase--flip's margin-right:auto then keeps the unit on
   the page's left margin instead of floating in the middle of its column. */
/* width:auto matters. The base rule gives the image a full-width box and
   lets object-fit letterbox the artwork inside it, which silently re-centres
   an upright device and leaves margin-right:auto with nothing to push
   against. Shrinking the box to the artwork puts the unit back on the page's
   left margin, in line with the masthead and every heading below it. */
.showcase--tall .showcase-art img{
  width:auto;max-width:100%;max-height:min(44svh,412px);object-fit:fill;
}

/* The accent rule off the product card. It is the one place each screen
   is allowed its product's colour, and it stays on the copy rather than
   spanning the screen — a full-bleed 2px band would sit under the fixed
   masthead at the snap point and never be seen. */
.showcase-copy{border-top:2px solid var(--pc);padding-top:var(--sp-5)}
/* Same treatment the product page gives its own eyebrow. The screen and
   the page it links to were showing the identical word in two different
   colours. --pc-text, never --pc: the bright accents are built for the
   products' dark surfaces and measure under 2:1 as type on paper. */
.showcase-copy .ag-label{color:var(--pc-text)}

.showcase-index{
  display:flex;align-items:center;gap:var(--sp-3);
  margin:0 0 var(--sp-4);max-width:none;
  font-family:var(--ag-label);font-size:var(--t-micro);font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ag-fg-faint);
}
.showcase-index .ag-figure{color:var(--pc-text)}
.showcase-index span + span::before{
  content:"";display:inline-block;vertical-align:middle;
  width:18px;height:var(--ag-hair);background:var(--ag-rule-strong);
  margin-right:var(--sp-3);
}

.product-title{margin-block:var(--sp-3) var(--sp-2);
  font-weight:600;letter-spacing:-.012em;line-height:1.15}
.showcase .product-title{font-size:var(--t-h2)}
.showcase--lead .product-title{font-size:var(--t-h1)}

.tagline{
  font-family:var(--ag-label);font-size:var(--t-label);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ag-fg-faint);display:block;
  margin-bottom:var(--sp-4);
}
.showcase-copy p{max-width:48ch}
.showcase .cta{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin-top:var(--sp-5)}

/* Capped against the viewport, not just the column: on a short laptop
   an uncapped illustration is what pushes a screen past 100svh and
   quietly strands the buttons under the fold. */
.showcase-art img{
  display:block;width:100%;height:auto;
  max-height:min(56svh,540px);object-fit:contain;
}
.showcase--flip .showcase-art img{margin-right:auto}

/* Specs sit under each product as chips rather than a table — there are
   only four of them and a table would out-weigh the prose above it. */
.specs{
  list-style:none;margin:var(--sp-4) 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);
}
.specs li{
  font-family:var(--ag-label);font-size:var(--t-micro);letter-spacing:.06em;
  color:var(--ag-fg-faint);font-variant-numeric:tabular-nums;
}
.specs li::before{content:"— ";opacity:.55}

@media (max-width:900px){
  .showcase,.showcase--lead,.showcase--tall{grid-template-columns:1fr;gap:var(--sp-6)}
  /* Artwork after the copy on both, whichever side it takes on wide
     screens — a picture of a thing you have not been introduced to yet
     is just a rectangle. */
  .showcase--flip .showcase-art{order:0}
  /* Stacked, the upright unit has to give up more height than the wide one
     or it pushes the buttons under the fold on a short screen. */
  .showcase-art img{max-height:38svh}
  .showcase--tall .showcase-art img{max-height:44svh}
}

/* ---------- common ---------------------------------------------------- */

.community .ag-spec th{width:150px}
/* Five short rows in a whole screen read as a table that got lost. Given a
   screen to itself the table takes it: the rows open up with the viewport
   rather than sitting in the middle of it. Scoped to the same query that
   turns snapping on, since it is only a full screen there. */
@media (min-width:901px) and (min-height:680px){
  .common .ag-spec th,.common .ag-spec td{padding-block:clamp(10px,1.7svh,22px)}
}
@media (max-width:520px){
  .common .ag-spec th,.common .ag-spec td{display:block;width:auto;padding-right:0}
  .common .ag-spec th{border-bottom:0;padding-bottom:2px}
}

/* ---------- footer ---------------------------------------------------- */

/* On the home page the footer shares the closing screen with About and
   is pushed to the foot of it; on a product page it ends the document
   in the ordinary way. */
/* The closing screen carries two things at once. The auto margins give
   all the free space to the About block, which centres it in whatever is
   left above the footer, and push the footer to the foot of the screen —
   without taking it out of flow, so the same rule still reads correctly
   at the sizes where the section is an ordinary block. */
.closing .ag-row{margin-block:auto}
.closing .site-footer{margin-top:var(--sp-8)}

.site-footer{
  border-top:var(--ag-hair) solid var(--ag-rule);
  padding-block:var(--sp-6) var(--sp-2);
}
body:not(.home) .site-footer{margin-top:var(--sp-9);
  padding-block:var(--sp-7) var(--sp-8)}
.site-footer .ag-wrap{
  display:flex;justify-content:space-between;align-items:flex-end;
  gap:var(--sp-6);flex-wrap:wrap;
}
.site-footer img{height:36px;width:auto}
.footer-links{display:flex;flex-direction:column;gap:6px;text-align:right}
.footer-links a{
  font-family:var(--ag-label);font-size:var(--t-micro);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ag-fg-muted);text-decoration:none;
}
.footer-links a:hover{color:var(--ag-fg);text-decoration:underline;
  text-underline-offset:.2em}
.colophon{font-family:var(--ag-label);font-size:var(--t-micro);
  color:var(--ag-fg-faint);letter-spacing:.04em;margin:0;max-width:none}
@media (max-width:560px){
  .site-footer .ag-wrap{align-items:flex-start}
  .footer-links{text-align:left}
}

/* ---------- theme-paired artwork -------------------------------------- */
/* The lockups are flat ink-on-paper files, so the page swaps which one it
   shows rather than filtering a single image.

   These rules are the ONLY place `display` is set on the paired images.
   Sizing rules above deliberately omit it: a selector like `.footer img`
   would carry more specificity than `.only-dark` and un-hide the wrong
   artwork. */

.only-light,.only-dark{display:none}
.only-light{display:block}
@media (prefers-color-scheme:dark){
  html:not([data-theme="light"]) .only-light{display:none}
  html:not([data-theme="light"]) .only-dark{display:block}
}
html[data-theme="dark"] .only-light{display:none}
html[data-theme="dark"] .only-dark{display:block}

/* ============================================================
   PRODUCT PAGES
   ============================================================ */

/* The page belongs to one product, so it may carry that product's colour —
   but on the same terms as a card on the homepage: one rule and one label,
   not a tinted page. --pc comes from the .ag-product--<name> modifier on
   <body>, which sets the variable without the card's border. */
.product-page .product-hero{border-top:2px solid var(--pc);padding-top:var(--sp-5)}
.product-page .product-hero .ag-label{color:var(--pc-text)}

.product-hero{padding-bottom:var(--sp-8)}
.product-hero .ag-display{font-size:var(--t-h1);margin-block:var(--sp-3) var(--sp-2)}
.product-hero .ag-lead{max-width:50ch}
.product-hero .cta{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin-top:var(--sp-6)}

/* Numbered because these really are sequences — a fixed signal order in one
   case, the order you actually do things in the other. Not decoration. */
.steps{list-style:none;counter-reset:step;margin:0;padding:0;max-width:var(--ag-measure)}
.steps li{
  counter-increment:step;display:grid;grid-template-columns:26px minmax(0,1fr);
  gap:var(--sp-3);padding:var(--sp-4) 0;
  border-top:var(--ag-hair) solid var(--ag-rule);
}
.steps li::before{
  content:counter(step,decimal-leading-zero);
  font-family:var(--ag-label);font-size:var(--t-micro);
  color:var(--pc-text,var(--ag-fg-faint));padding-top:.5em;
  font-variant-numeric:tabular-nums;
}
.steps b{display:block;font-family:var(--ag-display);font-weight:500;
  font-size:var(--t-h3);letter-spacing:-.006em;margin-bottom:2px;color:var(--ag-fg)}
.steps p{margin:0;color:var(--ag-fg-muted);font-size:var(--t-small)}
.steps p + p{margin-top:6px}

.backlink{
  display:inline-block;margin-top:var(--sp-7);
  font-family:var(--ag-label);font-size:var(--t-label);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ag-fg-muted);text-decoration:none;
}
.backlink:hover{color:var(--ag-fg);text-decoration:underline;text-underline-offset:.25em}

.nav a[aria-current="page"]{color:var(--ag-fg)}

/* Community lanes: the destination sits at the end of its own line so the
   table still reads as a spec sheet rather than a list of buttons. */
.community-link{
  display:inline-block;margin-left:var(--sp-2);
  font-family:var(--ag-label);font-size:var(--t-label);
  letter-spacing:.12em;text-transform:uppercase;
  white-space:nowrap;text-decoration-color:var(--ag-rule-strong);
}
