/* ==========================================================================
   Factbox — /join and /start.

   Loaded after css/app.css and css/account.css. It uses their tokens and adds
   no colour of its own: every value below is a var() from app.css's :root.
   There is not one hex literal in this file, on purpose — the site was
   repainted onto a light palette in a single afternoon and the things that
   broke were the ones carrying their own colours.

   WHAT THIS FILE IS FOR, AND WHAT IT USED TO BE FOR.

   /join was two things on one URL: five screens of onboarding questions, and
   a checkout. The questions are retired — the conversion flow asks for an
   account inside the story now, in the sheet js/recommend.js puts over it —
   and js/start.js, which drove them, is gone with them. So:

       /join   the checkout. The sign-up form and the plan picker are styled
               by css/account.css exactly as they were; nothing in here
               touches a .jn- selector, so the plan picker cannot be
               restyled by accident.
       /start  one real screen with one real door: a promise, and a button
               that goes to /join. It is the only page left that uses the
               .ob / .ob-top / .ob-mark / .ob-stage / .st-screen / .ob-centre
               / .ob-sub / .ob-act block below, and it is why that block is
               still here.

   WHAT WAS REMOVED WITH THE QUESTIONS: the story-behind-the-sheet layer
   (.ob-behind*), the sheet itself (.ob-sheet), the back button, the progress
   track, the option cards and their ticks (.ob-opt*, .ob-tick), the
   affirmation's figure (.ob-stat*), the result screen's rows (.ob-row,
   .ob-card), and the two body classes js/start.js used to hide the site
   chrome (body.ob-on, body.ob-over). None of them has any markup left to
   style. Bringing the flow back means bringing them back with it.

   ---------------------------------------------------------------------------
   THE THREE RULES THIS FILE EXISTS TO KEEP

   1. NOTHING TAPPABLE BELOW --bottom-safe. Every reader arrives in the
      Instagram or TikTok webview, whose toolbar is drawn over the bottom
      ~13vh of the viewport. The column carries that much padding underneath,
      and the primary button is pushed to the bottom of the column with
      `margin-top:auto` — so its bottom edge is (viewport - bottom-safe - 8px)
      BY CONSTRUCTION rather than by a number someone tuned once. The column is
      height-capped and the content scrolls inside it, so this holds at any
      viewport rather than at the three sizes someone remembered to check; the
      short-viewport blocks at the end of the file only stop it needing to.

   2. ONE SCREEN AT A TIME, AND THE REST ARE display:none. Not opacity:0, not
      visibility:hidden. A hidden button that still takes a tap is a real bug
      this flow has had.

   3. EVERY HIDEABLE THING SHIPS ITS OWN [hidden] RULE. `.go{display:block}`
      in app.css is (0,1,0) and beats the user agent's `[hidden]{display:none}`
      (0,0,1) — so `<button class="go" hidden>` renders anyway. That is live in
      this repo's history: a Continue button that carried `hidden` and showed
      up regardless, and separately `.ob` itself, which made "Already have an
      account? Sign in" look like a dead button. Any selector below that sets
      `display` on something the script hides is followed immediately by its
      `[hidden]` twin, and the rest are declared together at the end.
   ========================================================================== */


/* The story's name, so "your story" is a story with a name on it. Its own
   opaque ground: this is the one piece of type on the flow that sits over
   artwork, and --night under it is what the ratio is measured against. */

/* ==========================================================================
   2 · The column, and the sheet inside it
   ========================================================================== */

.ob{
  /* BOUNDED, not just tall. min-height alone lets a long screen grow the
     column past the viewport, and then the primary button is below the fold —
     which is the same failure as being under the Instagram toolbar, arrived at
     from the other direction. Capping the height and letting the ANSWERS
     scroll inside it makes the invariant hold at every size instead of at the
     three someone remembered to tune. */
  min-height:100vh; min-height:100dvh;
  max-height:100vh; max-height:100dvh;
  /* 440-480px of content, centred, with the gutter outside it. */
  max-width:calc(480px + 36px);
  margin:0 auto;
  padding:var(--top-safe) 18px calc(var(--bottom-safe) + 8px);
  display:flex; flex-direction:column;
  position:relative; z-index:1;
}
/* The rule this file's own header (point 3) says every hideable thing must
   ship — and the one place it was forgotten, on the container that matters
   most. `display:flex` above is (0,1,0) and beats the user agent's
   `[hidden]{display:none}`, so `stop()` setting the attribute changed
   nothing: the onboarding stayed 932px tall with hidden="true" on it, and
   "Already have an account? Sign in" opened the sign-in panel 1279px further
   down the page, below the fold, behind an onboarding that had not moved.
   The reader tapped, saw the same screen, and concluded the button was dead. */
.ob[hidden]{display:none !important}

/* Everything the reader answers lives on this. With nothing behind it, it is
   an invisible pass-through box. With a story behind it, it becomes the
   sheet. */

/* --- chrome: a wordmark, a thin bar, and a Back arrow. Nothing else. ------ */

/* A three-column grid, not a flex row, and every child is placed EXPLICITLY.
   The Back arrow is display:none on the first screen, and in a flex row that
   collapses its space and slides the wordmark left — it visibly jumps between
   screen 1 and screen 2, which is the one piece of chrome that is supposed to
   stay put. Fixed columns keep the gap whether or not the arrow is in it, and
   the explicit grid-column stops auto-placement filling the empty cell. */
.ob-top{
  display:grid;
  grid-template-columns:var(--tap) 1fr var(--tap);
  align-items:center;
  min-height:var(--tap);
}

/* The wordmark is centred whether or not the Back arrow is there, so it does
   not shift sideways between screen 1 and screen 2. It is a <p> and not an
   <a> — see the comment beside it in join.html. */
.ob-mark{
  grid-column:2; text-align:center; margin:0;
  font-size:var(--fs-micro); font-weight:var(--w-head);
  letter-spacing:var(--ls-mark); color:var(--accent-ink);
  /* the wordmark is set in caps and the letter-spacing pads the last glyph */
  padding-left:var(--ls-mark);
}
/* A spacer the same width as the arrow, so "centred" is actually centred. */

/* --- the progress bar ---------------------------------------------------- */

/* ==========================================================================
   3 · The stage, and one screen at a time
   ========================================================================== */

.ob-stage{
  /* min-height:0 on every link in the chain, or a flex child refuses to
     shrink below its content and the scroll region never scrolls. This is the
     whole trick and it is easy to delete by accident. */
  flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column;
  /* Questions sit upper-middle rather than jammed under the bar. */
  padding-top:clamp(16px, 6vh, 56px);
}
/* Less lift when there is a sheet: the sheet's own lip is already the gap. */

.st-screen{
  flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column;
  width:100%;
}
/* Rule 3. .st-screen sets display, so it must un-set it. */
.st-screen[hidden]{display:none !important}

/* The fade-and-lift between screens. Applied by the script on every show, and
   dropped for a reader who asked for less motion. */
@media (prefers-reduced-motion:no-preference){
  .st-screen.is-in{animation:ob-in .30s cubic-bezier(.22,.61,.36,1) both}
}
@keyframes ob-in{
  from{opacity:0; transform:translateY(10px)}
  to  {opacity:1; transform:none}
}

/* ==========================================================================
   4 · Type. One idea per screen, so the headline can be large.

   PLAIN HEADLINE TEXT. No box, no rule, no card around a question — the
   question is the loudest thing on the screen because it is the biggest, not
   because it is in a frame.
   ========================================================================== */

.st-screen h1,
.st-screen h2{
  margin:0;
  font-size:var(--fs-h1);
  font-weight:var(--w-head);
  line-height:var(--lh-head);
  letter-spacing:var(--ls-head);
  color:var(--parchment);
}

.ob-sub{
  margin:10px 0 0;
  font-size:var(--fs-body); font-weight:var(--w-body);
  line-height:var(--lh-body); color:var(--dim);
}

/* --- the promise, above the first question ------------------------------- */

/* "Pick up to 2." — sits with the answers, not with the question. */

/* ==========================================================================
   5 · Answer cards
   ========================================================================== */

/* The example line under a Q1 label. These are FBTAX's own notes about what
   is actually in each group — never a claim the stories do not make. */

/* The tactile beat: a small squeeze on the press. */

/* Selected. Obvious without shouting: the accent wash, the accent hairline,
   and a filled tick that only exists when it is on. */

/* THE CAP, MADE VISIBLE. Q1 takes two answers; the third tap on a fresh card
   does nothing, and a control that does nothing without saying so reads as
   broken. So at two, the unchosen cards drop to the page's own ground and
   lose their example line. NOT opacity: a translucent label is an unreadable
   label, and these still have to be readable to be understood as "not now".
   --dimmer on --ground is 4.6:1, which clears body text on its own merits. */

/* "Recommended", on the five-minute option. */

/* ==========================================================================
   6 · The action block, pinned to the bottom of the column
   ========================================================================== */

 /* The scrolling body of a screen that is neither a question list nor a
    centred statement — the result screen, which has a summary under its
    headline. */

.ob-act{
  margin-top:auto;
  flex:0 0 auto;
  padding-top:24px;
}
.ob-act .go{margin-top:0}
/* The result screen's primary control is an <a>, so it works with no script at
   all. app.css's .go was written for <button> and never resets the anchor's
   underline or centres its label — the one other anchor wearing .go on this
   site carries both as inline styles. Doing it here instead. */
.ob-act a.go{
  text-decoration:none; text-align:center; line-height:1.25;
}
/* Rule 3 again, and this is the one that has actually shipped wrong: .go
   carries display:block from app.css, which outranks the UA [hidden] rule. */
.ob-act .go[hidden]{display:none !important}

/* The same control as an <a> — the quiet way back to the story on the locked
   ending. .ob-tiny already wins the colour (0,1,0 over app.css's a{color:
   inherit}); the underline and the line box are what an anchor still needs. */

/* ==========================================================================
   7 · The affirmation — the one screen that is not a question
   ========================================================================== */

.ob-centre{
  flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column; justify-content:center;
  text-align:center;
  padding-bottom:6vh;
  overflow-y:auto; -webkit-overflow-scrolling:touch;
}

/* The one big number. Whatever it is, it is counted from data/index.json —
   see the note above RECALL_CLAIM_PCT in js/start.js. */

/* ==========================================================================
   8 · The result screen
   ========================================================================== */

/* The one sentence under the summary. .ob-stat-note is centred and capped for
   the affirmation screen; here it sits with the card. */

/* ==========================================================================
   9 · Hiding the site while the onboarding is on screen
   ---------------------------------------------------------------------------
   The nav, the account insignia, the marketing headline, the footer and the
   Privacy/Terms/Support line are all part of /join and all belong to the money
   side of it. They are hidden while a question is showing and come back the
   moment the sign-up form or the plan picker does — the plan screen keeps its
   legal links, which is not a style decision.
   ========================================================================== */

/* The money panels live in the same <main>; while onboarding is on they are
   hidden by their own [hidden] attribute (css/account.css), and this simply
   stops the .lib padding from doubling up with .ob's. */

/* A READER WHO ALREADY PAYS. #jn-done says there is nothing to sign up for;
   these three said the opposite, from outside the five panels money(false)
   hides, so they stayed on screen above it. The wordmark, the nav and the
   legal line stay — a subscriber on this page wants those. */
body.jn-paid #jn-title,
body.jn-paid #jn-blurb,
body.jn-paid .jn-haveacct{display:none !important}

/* ==========================================================================
   10 · The wordmark on the money side
   ---------------------------------------------------------------------------
   FACTBOX goes to /explore everywhere on the site, so it is an <a> here. It is
   a wordmark and not a nav link: no underline, no link colour, and a focus
   ring of its own. `.mark` in app.css sets a margin-bottom, which does nothing
   on an inline element — hence display:inline-block, and hence this block
   rather than a bare href swap in the markup.

   NOT on the question screens. See the comment beside .ob-mark in join.html.
   ========================================================================== */

.mast a.mark{
  display:inline-block;
  text-decoration:none;
  color:var(--accent-ink);
}
.mast a.mark:focus-visible{
  outline:2px solid var(--accent-ink); outline-offset:3px; border-radius:6px;
}

/* ==========================================================================
   11 · Short viewports
   ---------------------------------------------------------------------------
   Rule 1 only holds while the column FITS. 375x667 is 265px shorter than the
   phone this was drawn on, and landscape is shorter still. Both tighten the
   same things — the lift above the question, the gap between cards, the peek
   above the sheet, and the headline — rather than introducing a second layout.
   ========================================================================== */

@media (max-height:740px){
  .ob-stage{padding-top:clamp(8px, 2.5vh, 22px)}
  
  
  
  
  .ob-act{padding-top:16px}
  .ob-centre{padding-bottom:2vh}
  
  
  
}

@media (max-height:620px){
  .st-screen h1,
  .st-screen h2{font-size:var(--fs-h2)}
  .ob-sub{margin-top:6px; font-size:var(--fs-note)}
  
  
  
  
  
  
  
  
  .ob-act{padding-top:12px}
  .ob-act .go{padding:12px 20px}
}

/* Desktop: the column stays a phone-width column. A questionnaire that
   stretches to 1440px is a website with questions in it, which is the thing
   this rebuild is not. */
@media (min-width:900px){
  .ob{padding-top:calc(var(--top-safe) + 24px)}
  .ob-stage{padding-top:clamp(24px, 9vh, 90px)}
  
}

/* ==========================================================================
   The [hidden] twins, for every class in this file that sets a display.

   Point 3 of this file's own header says each one must ship with its class,
   and one was missed — `.ob` — which is how "Already have an account? Sign
   in" came to do nothing visible: the attribute was set, `display:flex` beat
   the user agent's `[hidden]{display:none}`, and the onboarding stayed on
   screen with the sign-in panel opening below the fold behind it.

   So the rest are declared here rather than left to be remembered one at a
   time. An element that never carries the attribute is unaffected; the cost
   of a rule that never matches is nothing, and the cost of the missing one
   was a dead-looking button on the way into the funnel.
   ========================================================================== */
.ob-behind-art[hidden],
.ob-behind-veil[hidden],
.ob-card[hidden],
.ob-centre[hidden],
.ob-opt-txt[hidden],
.ob-opts[hidden],
.ob-promise-h[hidden],
.ob-promise-p[hidden],
.ob-row[hidden],
.ob-stage[hidden],
.ob-tick[hidden],
.ob-tiny[hidden],
.ob-top[hidden]{display:none !important}
