/* On — The Oniversity
   Tokens lifted from the design file and assets/TOKENS.md. The flow is
   prototype C, Sheets, from docs/on-niversary/prototypes/c-sheets.html: a
   full-bleed shelf of the two shoes to swipe between, on ink; the questions
   stack up from the bottom as sheets, the way a phone's own sheets do; size is
   a ruler you drag. On save the sheets drop and the shoe lifts.

   Every rule under "real device" at the foot of this file is one of the rules
   in docs/on-niversary/README.md § Browsers and screens, with the reason it
   exists. They are lifted from the prototype, not re-derived. Nothing here is
   optional on the day. */

@font-face{font-family:'On Semi Mono';src:url('assets/fonts/OnDiatypeSemi-Mono-Regular.woff2') format('woff2'),url('assets/fonts/OnDiatypeSemi-Mono-Regular.woff') format('woff');font-weight:400;font-display:swap}
@font-face{font-family:'On Semi Mono';src:url('assets/fonts/OnDiatypeSemi-Mono-Medium.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'On Semi Mono';src:url('assets/fonts/OnDiatypeSemi-Mono-Bold.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'On Mono';src:url('assets/fonts/OnDiatypeMono-Regular.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'On Mono';src:url('assets/fonts/OnDiatypeMono-Medium.woff2') format('woff2');font-weight:500;font-display:swap}

:root{
  --ink:#000;
  --ink-2:#6E6E6E;
  --ink-3:#8A8A8A;
  --ink-4:#9A9A9A;
  --ink-5:#B5B0A8;
  --line:#E4E1DC;
  --wash:#F4F2EE;
  --wash-2:#F0EEEA;
  --canvas:#EFEDE9;
  --paper:#fff;

  --night:#0B0B0B;
  --fog:rgba(255,255,255,.55);
  --fog-2:rgba(255,255,255,.3);

  --panel-w:390px;
  --panel-h:844px;

  --font:'On Semi Mono',ui-sans-serif,system-ui,sans-serif;
  --mono:'On Mono',menlo,consolas,monospace;

  --sheet:.5s cubic-bezier(.32,.72,0,1);
  --rise:cubic-bezier(.2,.8,.2,1);
}

*,*::before,*::after{box-sizing:border-box}

/* A class beats the browser's own `[hidden]{display:none}`, so without this
   line the hidden attribute does nothing. */
[hidden]{display:none !important}

html{-webkit-text-size-adjust:100%;color-scheme:dark}

/* The page never scrolls. The shelf and the sheet bodies are the only scroll
   containers on the surface, because Safari's toolbars move when the document
   scrolls and take a bottom-pinned sheet with them. */
html,body{height:100%;overflow:hidden}

body{
  margin:0;
  background:var(--canvas);
  color:var(--ink);
  font-family:var(--font);
  -webkit-font-smoothing:antialiased;
}

button{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;cursor:pointer}
input{font-family:inherit;color:inherit}
button:focus-visible,input:focus-visible{outline:2px solid currentColor;outline-offset:2px}

.mono{font-family:var(--mono);letter-spacing:.12em}

@keyframes drift{0%,100%{transform:translateY(0) rotate(0)}50%{transform:translateY(-8px) rotate(-1.5deg)}}
@keyframes rise{0%{transform:translateY(12px);opacity:0}100%{transform:translateY(0);opacity:1}}
@keyframes lift{0%{transform:translateY(0) rotate(0) scale(1)}100%{transform:translateY(-36px) rotate(-9deg) scale(1.08)}}

/* ---------- stage ---------- */

.stage{
  min-height:100%;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:18px;
  padding:44px 20px 60px;
}
.stage__tag,.stage__step{
  display:flex;
  align-items:center;
  gap:10px;
  font-family:var(--mono);
  font-size:10px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.stage__step{color:var(--ink-5);letter-spacing:.1em}
.stage__logo{width:20px;height:20px;display:block}

.phone{
  width:var(--panel-w);
  height:var(--panel-h);
  background:var(--night);
  color:var(--paper);
  border-radius:42px;
  overflow:hidden;
  position:relative;
  flex:none;
  box-shadow:0 24px 60px rgba(0,0,0,.18),0 2px 6px rgba(0,0,0,.06);
}

/* ---------- the shelf ---------- */

.head{
  position:absolute;top:0;left:0;right:0;z-index:3;
  display:flex;align-items:center;justify-content:space-between;
  padding:60px 24px 0;
  pointer-events:none;
}
.head__logo{width:26px;height:26px;display:block;filter:invert(1)}
.head__tag{font-size:10px;letter-spacing:.14em;color:var(--fog)}

.shelf{
  position:absolute;inset:0;
  overflow-y:auto;
  scroll-snap-type:y mandatory;
  /* A drag that reaches the end of the shelf must not become Chrome's
     pull-to-refresh or Safari's rubber band. */
  overscroll-behavior:contain;
  scrollbar-width:none;
  transition:transform var(--sheet),opacity var(--sheet);
  transform-origin:50% 40%;
}
.shelf::-webkit-scrollbar{display:none}
.phone.has-sheet .shelf{transform:scale(.94) translateY(-14px);opacity:.5}
.phone.is-saved .shelf{overflow:hidden}

.slide{
  height:100%;
  scroll-snap-align:start;
  scroll-snap-stop:always;
  display:flex;flex-direction:column;
  padding:110px 28px 40px;
  position:relative;
}
/* The wrapper drifts, never the image: the drop-shadow filter below sits on
   the static <img>, because a filter on an animated element re-rasters every
   frame on a low-end Android. */
.slide__img{
  flex:1;min-height:0;
  display:flex;align-items:center;justify-content:center;
  animation:drift 7s ease-in-out infinite;
}
.slide__img img{
  max-width:100%;max-height:100%;
  object-fit:contain;display:block;
  filter:drop-shadow(0 30px 40px rgba(0,0,0,.6));
}
.slide:nth-child(2) .slide__img{animation-delay:-3.5s}
.phone.is-saved .slide.is-chosen .slide__img img{animation:lift .8s var(--rise) both}

.slide__text{flex:none;display:flex;flex-direction:column;gap:14px}
.slide__eyebrow{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--fog)}
.slide__name{margin:0;font-size:40px;line-height:.98;font-weight:700;letter-spacing:-.03em;text-wrap:balance}
.slide__sub{margin:0;font-size:15px;line-height:1.35;color:var(--fog)}
.slide__go{margin-top:6px}

/* The dots are buttons, 44px tall each: the swipe has a tap. */
.dots{
  position:absolute;right:4px;top:50%;
  transform:translateY(-50%);
  display:flex;flex-direction:column;z-index:3;
}
.dot{width:36px;min-height:44px;display:flex;align-items:center;justify-content:center}
.dot::before{content:'';width:4px;height:4px;border-radius:999px;background:var(--fog-2);transition:height .3s var(--rise),background .3s}
.dot.is-on::before{height:18px;background:var(--paper)}
.phone.is-saved .dots,.phone.is-saved .slide:not(.is-chosen){display:none}

/* Every control has a min-height and never a height. Android's text scaling
   grows the words, and a fixed height clips them. */
.btn{
  min-height:54px;flex:none;
  border-radius:999px;
  background:var(--paper);color:var(--ink);
  display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:500;
  transition:background .2s,transform .15s,opacity .2s;
}
.btn:active{transform:scale(.985)}
.btn:disabled{opacity:.35;cursor:default;transform:none}
.sheet .btn{background:var(--ink);color:var(--paper)}
.sheet .btn:disabled{background:var(--wash-2);color:var(--ink-5);opacity:1}
.btn--ghost{background:none;color:var(--paper);border:1px solid var(--fog)}

/* ---------- the receipt ---------- */

/* On save the slide's own words are replaced in place, so the shoe never
   leaves the screen it was chosen on. */
.slide__done{display:none;flex-direction:column;gap:12px}
.phone.is-saved .slide.is-chosen .slide__text > :not(.slide__done){display:none}
.phone.is-saved .slide.is-chosen .slide__done{display:flex}
.phone.is-saved .slide__done > *{animation:rise .5s var(--rise) both}
.phone.is-saved .slide__done > :nth-child(2){animation-delay:80ms}
.phone.is-saved .slide__done > :nth-child(3){animation-delay:160ms}
.phone.is-saved .slide__done > :nth-child(4){animation-delay:240ms}
.done__title{margin:0;font-size:34px;line-height:1;font-weight:700;letter-spacing:-.03em}
.facts{margin:0;font-size:15px;line-height:1.5;color:var(--fog)}
.facts b{color:var(--paper);font-weight:500}
.facts__line{display:block}
/* An iPhone SE with Display Zoom on is 320px wide. There a work email is wider
   than the line and ran off the screen. `app.js` lets it break before the @
   and holds "EU 42" together; this is the last resort for a word that is
   still wider than the line on its own. */
.facts,.summary{overflow-wrap:anywhere}

/* Where the seeding has got to. The dot fills when the queue drains. */
.status{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--fog);display:flex;align-items:center;gap:8px}
.status::before{content:'';width:6px;height:6px;border-radius:999px;background:var(--fog-2);transition:background .3s}
.status.is-saved::before{background:var(--paper)}
.status.is-rejected{color:var(--paper)}
.status.is-rejected::before{background:var(--paper)}

/* ---------- sheets ---------- */

.scrim{
  position:absolute;inset:0;
  background:rgba(0,0,0,.35);
  opacity:0;pointer-events:none;
  transition:opacity var(--sheet);
  z-index:4;
}
.phone.has-sheet .scrim{opacity:1;pointer-events:auto}

/* The sheets are white and say so, so Chrome's and Samsung Internet's
   auto-dark leaves the ink on paper. */
.sheet{
  position:absolute;left:0;right:0;bottom:0;
  height:74%;
  background:var(--paper);color:var(--ink);color-scheme:light;
  border-radius:28px 28px 0 0;
  padding:14px 24px 28px;
  display:flex;flex-direction:column;gap:16px;
  transform:translateY(104%);
  transition:transform var(--sheet),filter var(--sheet);
  z-index:5;
  will-change:transform;
}
.sheet.is-open{transform:translateY(0)}
.sheet.is-behind{transform:translateY(-16px) scale(.95);filter:brightness(.9)}
.sheet__handle{width:36px;height:4px;border-radius:999px;background:var(--line);align-self:center;flex:none}
/* The close link keeps the title's first line. A model name plus the question
   wraps to two lines on a 360px screen, and centred against a two-line title
   the link sits in the middle of nothing. */
.sheet__head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex:none}
.sheet__title{margin:0;font-size:24px;line-height:1.05;font-weight:700;letter-spacing:-.02em}
.sheet__sub{margin:4px 0 0;font-size:13px;color:var(--ink-2)}

/* Ten-pixel uppercase, and the way back out of every sheet. The words are
   small; the target a thumb has to find is not. */
.link{
  min-height:44px;flex:none;
  display:flex;align-items:center;
  font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);transition:color .2s;
}
/* Hover only where there is one: a chip must not stay lit after a finger
   leaves it. */
@media (hover:hover){.link:hover{color:var(--ink)}}

.sheet__body{
  flex:1;min-height:0;
  display:flex;flex-direction:column;gap:16px;
  overflow-y:auto;
  overscroll-behavior:contain;
  touch-action:pan-y;
  -webkit-overflow-scrolling:touch;
}
.sheet.is-open .sheet__body > *{animation:rise .45s var(--rise) both}
.sheet.is-open .sheet__body > :nth-child(2){animation-delay:70ms}
.sheet.is-open .sheet__body > :nth-child(3){animation-delay:140ms}

/* ---------- range ---------- */

.units{
  display:flex;gap:4px;padding:3px;flex:none;
  background:var(--wash);border-radius:999px;
  width:fit-content;position:relative;align-self:center;
}
.unit{
  position:relative;
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  min-height:36px;padding:6px 18px;border-radius:999px;
  color:var(--ink-3);transition:color .2s;z-index:1;
}
.unit[aria-pressed="true"]{color:var(--paper)}
.units__thumb{position:absolute;top:3px;bottom:3px;left:3px;width:calc(50% - 3px);border-radius:999px;background:var(--ink);transition:transform .35s var(--rise)}
.units[data-side="men"] .units__thumb{transform:translateX(100%)}

/* ---------- the ruler ---------- */

.readout{display:flex;flex-direction:column;align-items:center;gap:4px;flex:none}
.readout__eu{font-size:56px;line-height:1;font-weight:700;letter-spacing:-.04em;font-variant-numeric:tabular-nums}
.readout__us{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-4)}

.ruler{position:relative;flex:none;margin:0 -24px}
.ruler__strip{
  display:flex;
  overflow-x:auto;
  /* The drag along the ruler is claimed, so it never becomes a page gesture
     halfway through. */
  touch-action:pan-x;
  scroll-snap-type:x mandatory;
  scrollbar-width:none;
  padding:14px calc(50% - 30px) 10px;
  gap:0;
  overscroll-behavior-x:contain;
}
.ruler__strip::-webkit-scrollbar{display:none}
.rung{
  flex:none;width:60px;
  scroll-snap-align:center;
  display:flex;flex-direction:column;align-items:center;gap:6px;
  color:var(--ink-4);
  transition:color .2s,transform .25s var(--rise);
}
.rung__tick{width:1px;height:18px;background:currentColor;opacity:.5}
.rung__eu{font-size:15px;font-weight:500;font-variant-numeric:tabular-nums}
.rung.is-on{color:var(--ink);transform:scale(1.18)}
.ruler__needle{position:absolute;left:50%;top:0;width:2px;height:12px;margin-left:-1px;background:var(--ink);border-radius:2px;pointer-events:none}
.ruler__fade{position:absolute;top:0;bottom:0;width:60px;pointer-events:none}
.ruler__fade--l{left:0;background:linear-gradient(90deg,var(--paper),transparent)}
.ruler__fade--r{right:0;background:linear-gradient(270deg,var(--paper),transparent)}

/* ---------- office ---------- */

/* 16px, because iOS Safari zooms into any field smaller than that and does
   not zoom back out. Every input on this surface is 16px for that one reason. */
.search{
  min-height:48px;
  border:1px solid var(--line);border-radius:12px;
  padding:0 14px;font-size:16px;
  -webkit-appearance:none;appearance:none;outline:none;
  background:var(--paper);
  transition:border-color .2s;flex:none;
}
.search:focus{border-color:var(--ink)}
.search::placeholder{color:var(--ink-5)}

.regions{display:flex;flex-direction:column;gap:16px}
.region{display:flex;flex-direction:column;gap:8px}
.region__name{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-4)}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.office{
  min-height:40px;padding:0 16px;
  border:1px solid var(--line);border-radius:999px;
  font-size:14px;font-weight:500;
  display:flex;align-items:center;
  transition:border-color .2s,background .2s,color .2s,transform .15s;
}
@media (hover:hover){.office:hover{border-color:var(--ink)}}
.office:active{transform:scale(.96)}
.office[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.office--else{border-style:dashed}

/* ---------- you ---------- */

.field{display:flex;flex-direction:column;gap:7px;flex:none}
.field__label{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-4)}
.field input{
  min-height:50px;
  border:1px solid var(--line);border-radius:12px;
  padding:0 14px;font-size:16px;
  -webkit-appearance:none;appearance:none;outline:none;
  background:var(--paper);
  transition:border-color .2s;
}
.field input:focus{border-color:var(--ink)}
.field input::placeholder{color:var(--ink-5)}
/* The page has no red, so a wrong field is marked the way a focused one is:
   in ink, with the line under it saying what to change. */
.field input[aria-invalid="true"]{border-color:var(--ink)}
.field__note{margin:-9px 0 0;font-size:12px;line-height:1.45;color:var(--ink);flex:none}
.purpose{margin:0;font-size:12px;line-height:1.45;color:var(--ink-3)}
/* One sentence, not a row of parts. As a flex row the separators took the
   container's gap on one side and their own space on the other, so the line
   read unevenly. */
.summary{display:block;font-size:13px;line-height:1.5;color:var(--ink-2);flex:none}
.summary b{color:var(--ink);font-weight:500}

/* ---------- real device ---------- */

/* Full-bleed on a narrow screen and on anything you touch, in either
   orientation. A phone on its side is wider than 640px, and a coarse pointer
   is a finger. The frame above is for a desk. */
@media (max-width:640px),(max-height:520px),(pointer:coarse){
  .stage{padding:0;gap:0;min-height:100%}
  .stage__tag,.stage__step{display:none}
  /* 100vh first, 100dvh where the browser has it. `app.js` puts
     visualViewport on top of both when a keyboard is up. */
  .phone{width:100%;height:100vh;height:100dvh;border-radius:0;box-shadow:none}
  /* Safari 26 ignores `theme-color` and paints its bars from the body's
     background instead. On a desk the body is the canvas around the frame;
     on a phone the frame is the screen, so the body is ink too, or the bars
     above and below the shoe come out paper. */
  body{background:var(--night)}
  .head{padding-top:max(44px,env(safe-area-inset-top))}
  .slide{
    padding-top:max(100px,calc(env(safe-area-inset-top) + 60px));
    padding-bottom:max(32px,env(safe-area-inset-bottom));
  }
  .sheet{height:78%;padding-bottom:max(24px,env(safe-area-inset-bottom))}
}

/* A phone on its side: at 390px tall a column slide has no room for the shoe,
   so the shoe and the words share the width and the sheet takes the whole
   height. */
@media (max-height:520px){
  .head{padding-top:max(14px,env(safe-area-inset-top))}
  .slide{
    flex-direction:row;align-items:center;gap:24px;
    padding:max(56px,calc(env(safe-area-inset-top) + 40px))
            max(28px,env(safe-area-inset-right))
            max(20px,env(safe-area-inset-bottom))
            max(28px,env(safe-area-inset-left));
  }
  .slide__img{flex:1 1 50%;min-height:0;align-self:stretch}
  .slide__text{flex:1 1 50%}
  .slide__name{font-size:30px}
  .done__title{font-size:28px}
  .sheet{height:100%;border-radius:0;padding-top:max(10px,env(safe-area-inset-top))}
  .readout__eu{font-size:40px}
}

/* The keyboard. `app.js` sizes the phone to the visual viewport and the sheet
   follows, so the field and the button stay on screen: 78% of a 367px screen
   is not enough for a title, a field and a button. */
.phone.has-keyboard .sheet{height:100%;border-radius:0}

/* Every animation has a resting state. With this on, the flow is the same
   flow with no transitions — not a different one. */
@media (prefers-reduced-motion:reduce){
  .shelf,.sheet,.scrim,.units__thumb,.rung,.dot,.btn,.office,.status::before{transition:none}
  .slide__img,
  .slide__img img,
  .sheet.is-open .sheet__body > *,
  .phone.is-saved .slide__done > *,
  .phone.is-saved .slide.is-chosen .slide__img img{animation:none}
  .shelf,.ruler__strip{scroll-behavior:auto}
}
