/* ===========================================================================
   City Ale Link — Tap On
   Built to city-ale-link-identity/BRAND-SYSTEM.md.

   One signal ink. Night ink, clean stock, platform steel.
   The continuous line with five circular nodes is the only graphic device:
   it runs vertically on mobile and moves through the compositions on desktop.
   No cards, no ticket shapes, no badges, no boxed UI, no paper texture.

   Measured contrast, so the palette is used only where it holds up:
     signal on ink        5.42:1   text is fine
     ink on signal        5.42:1   button text is fine
     stock on ink        16.75:1
     steel on ink         8.25:1
     signal on stock      3.09:1   large display and graphics only
     signal-deep on stock 4.56:1   the small-text substitute for signal
     steel on stock       2.03:1   never used as text on stock
   =========================================================================== */

@font-face{font-family:"Archivo";src:url(/assets/fonts/archivo-400.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Archivo";src:url(/assets/fonts/archivo-500.woff2) format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"Archivo";src:url(/assets/fonts/archivo-700.woff2) format("woff2");font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"ArchivoB";src:url(/assets/fonts/archivo-black.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Anton";src:url(/assets/fonts/anton.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"ArchivoN";src:url(/assets/fonts/archivo-narrow-600.woff2) format("woff2");font-weight:600;font-style:normal;font-display:swap}

:root{
  --signal:#ff4b22;
  --signal-deep:#d2350f;   /* small text on stock only */
  --ink:#0d1625;
  --stock:#f7f6f1;
  --steel:#a9b0b4;

  --ink72:rgba(13,22,37,.72);
  --ink16:rgba(13,22,37,.16);
  --stock72:rgba(247,246,241,.72);
  --stock22:rgba(247,246,241,.22);

  --knock:var(--stock);    /* what a node punches out of the line */
  --rule:2px;
  --wrap:1240px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--stock);color:var(--ink);
  font-family:Archivo,system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:17px;line-height:1.55;-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
svg{display:block;width:100%;height:auto}
address{font-style:normal}

.wrap{max-width:var(--wrap);margin-inline:auto;padding-inline:22px}
.vh{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}
:focus-visible{outline:3px solid var(--signal);outline-offset:3px}
.on-stock :focus-visible{outline-color:var(--signal-deep)}
.on-signal :focus-visible{outline-color:var(--ink)}

.skip{position:absolute;left:-9999px;top:0;z-index:20;background:var(--signal);
  color:var(--ink);padding:14px 20px;font-weight:700;text-decoration:none}
.skip:focus{left:12px;top:12px}

h1,h2,h3{font-family:ArchivoB,Archivo,sans-serif;font-weight:400;margin:0;
  text-transform:uppercase;letter-spacing:-.055em;line-height:.86}
h3{letter-spacing:-.03em;line-height:1}
p{margin:0 0 1em}

/* AUCKLAND · NEW ZEALAND, section numbers, small caps furniture */
.meta{font-size:11px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  margin:0}
.on-ink .meta{color:var(--stock72)}
.on-ink .meta--sig{color:var(--signal)}
.on-stock .meta--sig{color:var(--signal-deep)}
.on-signal .meta{color:var(--ink)}

/* --------------------------------------------------------- the line ------ */
/* A vertical run of nodes. The line is one continuous rule; each node punches
   a hole in it, exactly as the printed pieces do.                            */
.line{list-style:none;margin:0;padding:0}
.line > li{position:relative;padding-left:52px}
.line > li::before{content:"";position:absolute;left:0;top:var(--node-top,22px);
  width:25px;height:25px;border:5px solid var(--signal);border-radius:50%;
  background:var(--knock);z-index:1}
/* one segment per stop, from this node to the next, so the run is continuous
   and always lands on centre whatever the row height */
.line > li::after{content:"";position:absolute;left:11px;
  top:calc(var(--node-top,22px) + 25px);bottom:calc(-1 * var(--node-top,22px));
  width:3px;background:var(--signal)}
.line > li:last-child::after{display:none}

/* ------------------------------------------------------------- surfaces -- */
.on-ink{background:var(--ink);color:var(--stock);--knock:var(--ink)}
.on-stock{background:var(--stock);color:var(--ink);--knock:var(--stock)}
.on-signal{background:var(--signal);color:var(--ink);--knock:var(--signal)}
.on-signal .line > li::before{border-color:var(--ink)}
.on-signal .line > li::after{background:var(--ink)}

/* ---------------------------------------------------------------- head --- */
.topbar{border-bottom:1px solid var(--stock22)}
.topbar .wrap{display:flex;align-items:center;justify-content:space-between;
  gap:20px;padding-block:16px}
.brand{display:flex;align-items:center;gap:14px;min-height:48px;
  text-decoration:none;color:var(--stock)}
.brand svg{width:168px}
.brand .meta{line-height:1.35}
.topnav ul{display:none;gap:26px;align-items:center;list-style:none;margin:0;padding:0}
.topnav a{font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--stock72);text-decoration:none;display:inline-flex;align-items:center;
  justify-content:center;min-height:48px;min-width:48px}
.topnav a:hover{color:var(--signal)}

/* ---------------------------------------------------------------- hero --- */
.hero{padding:48px 0 56px}
.hero__grid{display:grid;gap:44px}
/* The h1 carries both lines: the slogan reads as the headline, the descriptor
   says what the thing actually is. Rendered exactly as before. */
.hero h1{font-size:inherit;letter-spacing:normal;line-height:inherit}
/* TAP ON. is set in Archivo Narrow, a real condensed cut from the same
   superfamily as the body face — never a horizontally scaled Archivo Black.
   It echoes the tall, narrow letterforms of the CITY / ALE / LINK mark. */
/* Both lines of the h1 are set in Archivo Narrow — a real condensed cut from
   the same superfamily, never a horizontally scaled Archivo Black. It echoes
   the tall, narrow CITY / ALE / LINK letterforms, and it keeps the supporting
   line physically narrower than the headline it sits under. */
.hero__slogan{display:block;font-family:Anton,ArchivoN,ArchivoB,sans-serif;
  font-weight:400;font-size:clamp(62px,11.8vw,136px);letter-spacing:-.015em;
  line-height:.9;color:var(--signal)}
.hero .sub{display:block;font-family:ArchivoN,ArchivoB,Archivo,sans-serif;font-weight:600;
  text-transform:uppercase;letter-spacing:.005em;font-size:clamp(22px,2.4vw,34px);
  line-height:1.02;margin:14px 0 0;color:var(--stock)}
.hero .lead{font-size:clamp(16.5px,1.7vw,19px);max-width:40ch;margin:20px 0 0;
  color:var(--stock72)}
.hero .kicker{margin-bottom:22px}

/* the hero route: the line, the five stops, and the way into each one */
.hero__route{padding-top:6px}
.hero__route .meta{margin-bottom:20px}
.route-nav > li{--node-top:14px}
.route-nav > li + li{margin-top:4px}
.route-nav a{display:flex;align-items:baseline;gap:12px;padding:9px 0;min-height:48px;
  text-decoration:none;border-bottom:1px solid var(--stock22)}
.route-nav .n{font-size:11px;font-weight:700;letter-spacing:.16em;color:var(--steel);
  flex:none}
.route-nav .s{font-family:ArchivoB,Archivo,sans-serif;font-size:clamp(19px,2.2vw,25px);
  text-transform:uppercase;letter-spacing:-.035em;line-height:1}
.route-nav a{flex-wrap:wrap}
.route-nav .v{font-size:13px;color:var(--stock72);width:100%;margin-top:3px}
@media(min-width:34em){
  .route-nav a{flex-wrap:nowrap}
  .route-nav .v{width:auto;margin:0 0 0 auto;text-align:right}
}
.route-nav a:hover .s,.route-nav a:focus-visible .s{color:var(--signal)}

/* -------------------------------------------------------------- buttons -- */
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:52px;
  padding:15px 26px;font-size:13.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;text-decoration:none;border:var(--rule) solid transparent}
.btn--go{background:var(--signal);color:var(--ink)}
.btn--go:hover{background:#ff6a47}
.btn--ghost{border-color:var(--stock22);color:var(--stock)}
.btn--ghost:hover{border-color:var(--stock)}
.btn--ink{border-color:var(--ink);color:var(--ink)}
.btn--ink:hover{background:var(--ink);color:var(--stock)}
.on-signal .btn--ink:hover{color:var(--signal)}
.ext{margin-left:.5em;font-size:.85em}

/* --------------------------------------------------------------- bands --- */
.band{padding:74px 0}
.band__label{margin-bottom:44px}
.band h2{font-size:clamp(38px,6.4vw,88px)}
.lede{font-size:clamp(17px,2vw,21px);line-height:1.45;max-width:46ch;margin:0}
.on-ink .lede{color:var(--stock72)}
.on-stock .lede{color:var(--ink72)}

.split{display:grid;gap:36px}
.split p{margin:0 0 1.1em}
.split p:last-child{margin-bottom:0}
.split .body{font-size:17px;color:var(--ink72);max-width:52ch}

/* The passport closes the explanation as an unframed photographic beat. */
#how{padding-top:62px}
.passport-break{margin:0;background:#aaa7a2}
.passport-break picture{display:block}
.passport-break img{display:block;width:100%;max-width:1536px;height:auto;margin-inline:auto}

/* how it works: three steps strung along the line */
/* .steps only becomes a grid at 900px, so the gap above did nothing on the
   stacked layout. Padding rather than margin, so the connecting line — which
   runs to bottom:calc(-1 * var(--node-top)) — still reaches the next node. */
.steps{gap:46px;margin-top:44px}
.steps > li{padding-bottom:38px}
.steps > li:last-child{padding-bottom:0}
.steps h3{font-size:clamp(21px,2.4vw,27px);margin-bottom:8px}
.steps p{margin:0;font-size:16.5px;max-width:32ch}
.on-signal .steps p{color:var(--ink)}

/* -------------------------------------------------------------- venues --- */
.venues{padding:62px 0 84px}
.venues h2{font-size:clamp(38px,6.4vw,88px);margin-bottom:52px}
.route-stops > li{--node-top:38px}
.stop{display:grid;gap:18px;padding:34px 0;border-top:1px solid var(--ink16)}
.route-stops > li:first-child .stop{border-top:var(--rule) solid var(--ink)}
.stop__station{font-size:clamp(30px,4.6vw,52px)}
.stop__venue{font-family:Archivo,sans-serif;font-size:17px;font-weight:700;
  letter-spacing:.01em;text-transform:none;margin:8px 0 0}
.stop dl{margin:16px 0 0;display:grid;gap:4px 16px}
.stop dt{font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink72)}
.stop dd{margin:0 0 8px;font-size:15.5px}
.stop .acts{display:flex;gap:10px;flex-wrap:wrap;align-content:start}
.stop .acts .btn{min-height:48px;padding:12px 18px;font-size:12px}
.stop__mark{display:block;width:124px;aspect-ratio:1;background:var(--signal);
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.venues.on-signal .stop__mark{background:var(--ink)}
.venues.on-signal .stop dt{color:var(--ink)}
#about{padding-bottom:54px}

/* the impression lands once, on arrival — the only motion on the page */
@keyframes press{
  0%{opacity:0;transform:scale(1.24)}
  62%{opacity:1}
  78%{transform:scale(.985)}
  100%{opacity:1;transform:scale(1)}
}
.press{animation:press .5s cubic-bezier(.2,.9,.25,1) both;animation-delay:var(--d,0s)}
@media(prefers-reduced-motion:reduce){
  .press{animation:none;opacity:1;transform:none}
  *{transition-duration:.001ms!important;animation-duration:.001ms!important}
}

/* ------------------------------------------------------ stamp sequence -- */
/* Five registration circles waiting on the route line, and the five supplied
   stamps landing into them. Default state is FINISHED: every stamp visible,
   no transform. The unstamped starting state exists only inside .js-motion,
   which the script adds and which it never adds under reduced motion. That
   way "JavaScript blocked" and "JavaScript slow" both degrade to the full
   set rather than to an empty row. */
.seq{list-style:none;margin:52px 0 60px;padding:0;display:grid;gap:34px}
.seq__item{position:relative;display:grid;
  grid-template-columns:var(--slot,116px) minmax(0,1fr);
  gap:22px;align-items:center}
.seq__slot{position:relative;display:block;width:var(--slot,116px);
  aspect-ratio:1}

/* the guide the stamp lands into; it stays put, the stamp covers it */
.seq__reg{position:absolute;inset:0;border:2px solid var(--ink);opacity:.30;
  border-radius:50%}

.seq__mark{position:absolute;inset:0;background:var(--ink);
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  transform-origin:50% 50%}

.seq__name{display:block;line-height:1.25}
.seq__name b{display:block;font-size:20px;letter-spacing:-.01em}
.seq__name span{display:block;font-size:15px;color:var(--ink72)}
/* --ink72 is only 3.84:1 on the signal ground; the venue name carries real
   information, so it takes full ink and leans on size and weight for
   hierarchy instead of on tone */
.on-signal .seq__name span{color:var(--ink)}

/* the route, drawn between one slot centre and the next */
.seq__item::after{content:"";position:absolute;
  left:calc(var(--slot,116px) / 2 - 1.5px);
  top:calc(50% + var(--slot,116px) / 2);
  height:calc(50% - var(--slot,116px) / 2 + 34px);
  width:3px;background:var(--ink)}
.seq__item:last-child::after{display:none}

@keyframes impress{
  0%  {opacity:0;transform:translateY(-16px) scale(1.16) rotate(var(--r,3deg))}
  58% {opacity:1;transform:translateY(0) scale(.965)
       rotate(calc(var(--r,3deg) * .3))}
  78% {transform:translateY(0) scale(1.012) rotate(0deg)}
  100%{opacity:1;transform:none}
}

/* only ever hidden once the script has taken responsibility for showing it */
.js-motion .seq__mark{opacity:0}
.js-motion .seq.is-stamped .seq__mark{
  animation:impress .42s cubic-bezier(.2,.85,.25,1) both;
  animation-delay:calc(var(--i, 0) * 115ms)}

@media(prefers-reduced-motion:reduce){
  .js-motion .seq__mark{opacity:1}
  .js-motion .seq.is-stamped .seq__mark{animation:none;transform:none}
}

@media(min-width:560px){
  .seq{--slot:132px}
  .seq__name b{font-size:22px}
}

/* Desktop: one spacious horizontal run across the full content width. The
   route turns with it; nothing is squeezed and nothing scrolls sideways. */
@media(min-width:900px){
  .seq{--slot:150px;grid-template-columns:repeat(5,minmax(0,1fr));
    gap:0;margin:64px 0 68px;align-items:start}
  .seq__item{grid-template-columns:none;justify-items:center;
    text-align:center;gap:20px;padding:0 8px}
  .seq__item::after{left:calc(50% + var(--slot) / 2);
    top:calc(var(--slot) / 2 - 1.5px);
    width:calc(100% - var(--slot));height:3px}
  .seq__name b{font-size:19px}
  .seq__name span{font-size:14px}
}
@media(min-width:1100px){.seq{--slot:172px}}

#how-h span{display:block}
#how-h br{display:none}
@media(min-width:35em){#how-h span{display:inline}#how-h br{display:inline}}
.steps h3{display:flex;flex-direction:column;gap:2px;align-items:flex-start}
.steps__n{font-size:14px;letter-spacing:.16em;font-variant-numeric:tabular-nums;
  color:var(--ink72)}
.on-signal .steps__n{color:var(--ink);opacity:.66}
@media(min-width:900px){.steps h3{gap:6px}}

/* ------------------------------------------------------------ questions -- */
.split .body a:not(.btn){display:inline-flex;align-items:center;min-height:44px;
  font-weight:700;color:var(--signal-deep);text-underline-offset:3px}
.faq{border-top:var(--rule) solid var(--ink);margin-top:34px}
.faq details{border-bottom:1px solid var(--ink16)}
.faq summary{display:flex;justify-content:space-between;align-items:center;gap:18px;
  min-height:64px;padding:16px 0;cursor:pointer;list-style:none;
  font-family:ArchivoB,Archivo,sans-serif;font-size:clamp(17px,2vw,21px);
  text-transform:uppercase;letter-spacing:-.025em}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";flex:none;width:22px;height:22px;
  background:
    linear-gradient(var(--signal-deep),var(--signal-deep)) center/22px 3px no-repeat,
    linear-gradient(var(--signal-deep),var(--signal-deep)) center/3px 22px no-repeat;
  transition:transform .18s ease}
.faq details[open] summary::after{
  background:linear-gradient(var(--ink),var(--ink)) center/22px 3px no-repeat;
  transform:rotate(180deg)}
.faq p{margin:0 0 20px;max-width:58ch;color:var(--ink72);font-size:16.5px}

/* --------------------------------------------------------------- foot ---- */
.foot{padding:64px 0 52px}
.foot__top{display:flex;flex-wrap:wrap;gap:26px;justify-content:space-between;
  align-items:flex-start}
.foot .brand svg{width:210px}
.foot p{color:var(--stock72);margin:0 0 12px;max-width:56ch;font-size:15.5px}
.foot__by{margin-top:30px}
.foot ul{display:flex;flex-wrap:wrap;gap:4px 26px;margin:0;padding:0;list-style:none}
.foot ul a{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  text-decoration:none;display:inline-flex;align-items:center;min-height:48px;
  color:var(--stock);border-bottom:2px solid var(--signal)}
.foot .fine{border-top:1px solid var(--stock22);margin-top:34px;padding-top:20px;
  font-size:13px}

/* ==================================================== 640 px and up ======= */
@media(min-width:40em){
  .stop{grid-template-columns:1fr 116px;gap:26px}
  .stop__body{grid-column:1}
  .stop__mark{grid-column:2;grid-row:1;justify-self:end;width:132px}
  .stop dl{grid-template-columns:auto 1fr}
  .stop dd{margin-bottom:0}
}

/* ==================================================== 900 px and up ======= */
@media(min-width:56.25em){
  .topnav ul{display:flex}
  .brand svg{width:190px}
  .hero{padding:60px 0 72px}
  .hero__grid{grid-template-columns:1.15fr .85fr;gap:6vw;align-items:start}
  .split{grid-template-columns:1fr 1fr;gap:8vw}
  /* the line turns and runs through the composition */
  .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:34px}
  .steps > li{padding:56px 0 0}
  .steps > li::before{top:0;left:0}
  .steps > li::after{left:25px;top:11px;right:-34px;bottom:auto;
    width:auto;height:3px}
  .venues h2{margin-bottom:64px}
  .stop{grid-template-columns:minmax(0,1fr) auto 150px;gap:44px;padding:44px 0}
  .stop__mark{width:150px;grid-column:3}
  .stop .acts{grid-column:2;flex-direction:column;align-items:flex-start}
  .route-stops > li{padding-left:64px;--node-top:52px}
  .line::before{left:11px}
}

/* =================================================== 1200 px and up ======= */
@media(min-width:75em){
  body{font-size:17.5px}
  /* one line from 900px up, where the hero becomes two columns; below
     that the natural space break stays available */
  .hero__slogan{font-size:clamp(108px,10.3vw,148px);white-space:nowrap}
  .route-stops > li{padding-left:80px}
}
