/* The journey: the home as a scroll through the network's worlds.
   Pairs with app/hub_story.py. Loaded after sections.css, so the handful of
   selectors the two share are overrides on purpose.

   NO COLOUR VALUE IN THIS FILE. The world is --w-*, the money is --px-*, and
   the two never cross (S section 4.3).

   NOTHING HERE ANIMATES --x. The seam belongs to the finger: a CSS animation
   always beats an inline style, so an animated --x is a comparison control the
   visitor cannot command (T, settled after the owner reported the big slider
   as simply not working). The scroll work below moves opacity and transform
   and nothing else, and stops entirely under prefers-reduced-motion. */

/* ================================================================ a chapter
   One world, full width, in that brand's own ground, text, rule and display
   face. The chrome above it does not change: the top bar, the cart bubble, the
   sticky buy bar and every price stay on the instrument's graphite, which is
   why System B was refused (R2 section 2) and this is System A.

   Consecutive chapters meet edge to edge with no graphite between them. That
   is the whole transformation: the ground, the type and the atmosphere change
   four times on one scroll, and each change is a shop window. */
.ch{ padding-block:0 var(--px-14); }
@media (min-width:1024px){ .ch{ padding-block:0 var(--px-16); } }
/* the seam between two worlds */
.ch+.ch{ border-top:var(--px-hair) solid color-mix(in srgb, var(--px-ink) 40%, transparent); }

/* the world tab. Sticky inside its own chapter and gone with it, so the
   reader always knows which world they are standing in. It is the world's,
   not the platform's, so it wears --w-* and carries no number you can spend. */
.chtop{ position:sticky; top:44px; z-index:var(--px-z-rail);
  background:color-mix(in srgb, var(--w-ground) 88%, transparent);
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  border-bottom:var(--px-hair) solid var(--w-rule-soft); }
@media (min-width:1024px){ .chtop{ top:64px; } }
.chtop>.wrap{ display:flex; align-items:center; gap:var(--px-3);
  min-height:40px; font-size:var(--px-t-micro); color:var(--w-dim); }
.chtop .chno{ font-variant-numeric:tabular-nums; font-weight:700;
  letter-spacing:.1em; color:var(--w-accent); }
.chtop .chwho{ font-family:var(--w-display); text-transform:var(--w-case);
  font-size:var(--px-t-ui); color:var(--w-text); }
/* A phone's tab has room for the number and the maker. "LIBRARIES ACROSS THE
   NETW..." is not wayfinding, and the territory is two lines below it in
   .chmeta at every width. */
.chtop .chter{ display:none; }
@media (min-width:640px){
  .chtop .chter{ display:block; margin-left:auto; letter-spacing:.14em;
    text-transform:uppercase; white-space:nowrap; overflow:hidden;
    text-overflow:ellipsis; }
}

/* the head, the frame and the money. Source order is head, art, buy, which is
   the phone's reading order; the laptop puts the frame in its own column and
   stacks the other two beside it (R2 section 4.2, the two up). */
.chgrid{ display:grid; gap:var(--px-5); padding-top:var(--px-10); }
@media (min-width:1024px){
  .chgrid{ grid-template-columns:minmax(0,560px) minmax(0,1fr);
    grid-template-areas:"art head" "art buy"; column-gap:var(--px-16);
    row-gap:var(--px-6); align-content:center; padding-top:var(--px-14); }
  .chart{ grid-area:art; } .chhead{ grid-area:head; align-self:end; }
  .chbuy{ grid-area:buy; align-self:start; max-width:420px; }
}

.chhead{ position:relative; }
.chhead .label{ font-size:var(--px-t-micro); letter-spacing:.18em;
  text-transform:uppercase; color:var(--w-dim); font-family:var(--px-font);
  font-weight:600; }
.chhead h2{ font-family:var(--w-display); text-transform:var(--w-case);
  font-weight:500; font-size:clamp(40px,10vw,52px); line-height:1.02;
  letter-spacing:-.02em; margin-top:var(--px-3); color:var(--w-text); }
@media (min-width:1024px){ .chhead h2{ font-size:clamp(56px,4.6vw,72px); } }
.chlight{ font-family:var(--w-display); font-size:var(--px-t-h3);
  line-height:1.45; margin-top:var(--px-4); color:var(--w-text);
  max-width:44ch; }
@media (min-width:1024px){ .chlight{ font-size:22px; line-height:1.4; } }
.chmeta{ margin-top:var(--px-4); font-size:var(--px-t-ui); color:var(--w-dim);
  max-width:52ch; }

/* the aperture. Full bleed on a phone, exactly the 390 x 488 R2 asks for; a
   560 wide portrait frame on a laptop, because every rung on the ladder tops
   out at 714 px and a 1440 px band would be a 2x upscale. */
.chart{ margin-top:var(--px-6); }
.chart .cmp{ border-color:var(--w-rule);
  box-shadow:0 22px 50px color-mix(in srgb, var(--px-ink) 42%, transparent); }
@media (max-width:1023.98px){
  .chart .cmp{ margin-inline:calc(50% - 50vw); width:100vw;
    border-radius:0; border-inline:0; --cmp-ar:4/5; --cmp-handle:40px; }
}
@media (min-width:1024px){
  .chart{ margin-top:0; }
  .chart .cmp{ --cmp-ar:4/5; --cmp-handle:44px; width:100%; }
}
.chcap{ margin-top:var(--px-3); font-family:var(--w-display);
  font-size:var(--px-t-ui); line-height:1.4; color:var(--w-dim); }

/* the money. Everything in this block is --px-*: a price never wears a world
   (S section 4.3), and the struck price takes --px-was, which tokens.css
   computes per world from that world's own text at 80 per cent. */
.chbuy{ margin-top:var(--px-6); padding-top:var(--px-6);
  border-top:var(--px-hair) solid var(--w-rule-soft); }
@media (min-width:1024px){ .chbuy{ margin-top:0; } }
.chbuy .price{ margin-top:0; }
.chbuy .price .now{ font-size:38px; letter-spacing:-.03em; line-height:1; }
@media (min-width:1024px){ .chbuy .price .now{ font-size:46px; } }
.chbuy .trust{ color:var(--w-dim-2); }
.chbuy .reason{ margin-top:var(--px-2); font-size:var(--px-t-micro);
  color:var(--w-dim-2); }
.chbuy .own{ font-size:var(--px-t-h3); font-weight:700; color:var(--px-owned); }
@media (min-width:1024px){ .chbuy .cta,.chbuy .btn2,.chbuy .express{ max-width:360px; } }

/* ------------------------------------------------------------ the examples
   The device all ten hand written storefronts converged on: a numbered
   specimen entry. mossgrade's field guide plates, roamhue's numbered stops,
   savoryhue's courses, inklooks' folio lines. One photograph, four presets,
   the maker's own name and the maker's own written intent.

   A GRID THAT WRAPS, never a horizontal scroller: a before and after is
   DRAGGED along x and a scroller is SWIPED along x, so on a phone the two
   fight for the same axis and the scroller wins. */
.chex{ margin-top:var(--px-10); padding-top:var(--px-6);
  border-top:var(--px-hair) solid var(--w-rule-soft); }
.chex>.label{ font-size:var(--px-t-micro); letter-spacing:.16em;
  text-transform:uppercase; color:var(--w-dim); font-family:var(--px-font);
  font-weight:600; }
.exgrid{ list-style:none; padding:0; margin-top:var(--px-5);
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--px-5); }
@media (min-width:760px){ .exgrid{ grid-template-columns:repeat(4,minmax(0,1fr)); } }
@media (min-width:1024px){ .exgrid{ gap:var(--px-6); } }
.ex{ min-width:0; }
/* data-variant="ex", not "card": the card variant hides the "before" tag, and
   on a row whose whole argument is the comparison both tags stay. */
.ex .cmp{ --cmp-ar:440/789; --cmp-handle:28px; border-color:var(--w-rule); }
.ex .cmp .cmp-tag{ font-size:11px; padding:2px 5px; }
.exno{ margin-top:var(--px-3); font-family:var(--px-font); font-size:11px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--w-dim);
  font-variant-numeric:tabular-nums; }
.exname{ font-family:var(--w-display); text-transform:var(--w-case);
  font-size:var(--px-t-h3); line-height:1.2; color:var(--w-text); margin-top:2px; }
.exint{ margin-top:var(--px-2); font-size:var(--px-t-micro); line-height:1.5;
  color:var(--w-dim); }

.ch .exit{ display:inline-flex; min-height:44px; align-items:center;
  margin-top:var(--px-8); color:var(--w-text);
  border-bottom:var(--px-hair) solid var(--w-accent); }
.ch .exit:focus-visible{ outline:2px solid var(--px-focus); outline-offset:3px; }

/* ===================================================== find your light
   Photographs, not a price list. The price belongs on the card you arrive at,
   never on the door you are choosing between. */
.galgrid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--px-4); margin-top:var(--px-5); }
@media (min-width:1024px){
  .galgrid{ grid-template-columns:repeat(4,minmax(0,1fr)); gap:var(--px-6); }
}
.tile{ background:var(--px-ink-2); border:var(--px-hair) solid var(--px-rule);
  border-radius:var(--px-r-card); overflow:hidden; position:relative;
  display:flex; flex-direction:column; }
.tile .cmp{ border:0; border-radius:0; --cmp-ar:4/5; }
.tile .cmp-tag.before{ display:none; }
.tlink{ padding:var(--px-3) var(--px-3) var(--px-4); display:block; }
.tlink h3{ font-size:var(--px-t-h3); font-weight:700; line-height:1.25; }
.tlink .tmeta{ margin-top:2px; font-size:var(--px-t-micro); color:var(--px-dim);
  font-variant-numeric:tabular-nums; }
@media (min-width:1024px){
  .tile{ transition:border-color var(--px-t-enter) var(--px-e-enter); }
  .tile:hover{ border-color:var(--px-dim); }
  .tlink:hover h3{ text-decoration:underline; text-underline-offset:3px; }
}
.tlink:focus-visible{ outline:2px solid var(--px-focus); outline-offset:-2px; }

.galsub,.galmore{ margin-top:var(--px-10); padding-top:var(--px-5);
  border-top:var(--px-hair) solid var(--px-rule); }
.gal .label{ font-size:var(--px-t-micro); font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--px-dim); }
.subgrid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0 var(--px-6); margin-top:var(--px-2); }
@media (min-width:640px){ .subgrid{ grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media (min-width:1024px){ .subgrid{ grid-template-columns:repeat(4,minmax(0,1fr)); } }
.subgrid a,.gal .tlinks a{ display:flex; align-items:center;
  justify-content:space-between; gap:var(--px-3); min-height:48px;
  font-size:var(--px-t-ui);
  border-bottom:var(--px-hair) solid var(--px-rule); }
.subgrid a:hover,.gal .tlinks a:hover{ color:var(--px-chalk); }
.subgrid a:focus-visible,.gal .tlinks a:focus-visible{
  outline:2px solid var(--px-focus); outline-offset:2px; }
.subgrid .n,.gal .tlinks .n{ color:var(--px-dim);
  font-variant-numeric:tabular-nums; white-space:nowrap; }

/* ============================================== the brand page's own block */
.chstory .subline{ font-family:var(--w-display); font-size:var(--px-t-h3);
  line-height:1.45; }
.chstory .chex{ border-top:0; padding-top:0; margin-top:var(--px-6); }

/* ================================================== the scroll transitions
   CSS scroll driven animations, no JavaScript, no library, no scroll hijack.
   Each chapter's head and its example row arrive as the chapter arrives, and
   they animate opacity and transform only. Where view() is not supported
   (@supports below is the whole guard) nothing runs and nothing is missing:
   the elements are painted in their final state to begin with, so a browser
   without the timeline shows the finished page and never a blank one. */
@keyframes ch-rise{ from{ opacity:0; transform:translateY(16px); } to{ opacity:1; transform:none; } }
@keyframes ch-open{ from{ opacity:0; transform:translateY(24px) scale(.985); } to{ opacity:1; transform:none; } }

@supports (animation-timeline: view()){
  @media (prefers-reduced-motion:no-preference){
    .chhead>*,.chart,.chbuy,.chex>.label,.ex{
      animation:ch-rise linear both;
      animation-timeline:view();
      animation-range:entry 4% cover 22%;
    }
    .chart{ animation-name:ch-open; animation-range:entry 0% cover 26%; }
    /* the stagger is the source order, not a per element delay */
    .chhead>*:nth-child(2){ animation-range:entry 6% cover 24%; }
    .chhead>*:nth-child(3){ animation-range:entry 8% cover 26%; }
    .chhead>*:nth-child(4){ animation-range:entry 10% cover 28%; }
    .ex:nth-child(2){ animation-range:entry 6% cover 24%; }
    .ex:nth-child(3){ animation-range:entry 8% cover 26%; }
    .ex:nth-child(4){ animation-range:entry 10% cover 28%; }
  }
}

/* Reduced motion: hard cuts, nothing moves, and the same information is on
   the screen. tokens.css already crushes every duration to .01ms; this says
   it in the one way that cannot be argued with on a progress timeline. */
@media (prefers-reduced-motion:reduce){
  .chhead>*,.chart,.chbuy,.chex>.label,.ex,.tile{
    animation:none !important; transition:none !important;
    opacity:1 !important; transform:none !important; }
}

/* Low power (S section 6): the atmosphere goes, the chapters stay. */
.px-cheap .chtop{ -webkit-backdrop-filter:none; backdrop-filter:none;
  background:var(--w-ground); }
