/* The desktop layout. Everything that changes on a big screen is in this
   file, for the same reason motion.css exists: so "what is different on a
   laptop?" has one answer instead of ten.

   THE PROBLEM. The app is a 480px column centred in the window — a phone held
   up in the middle of a monitor, with everything outside it empty. That was
   right while Android was the only real target. It stopped being right the day
   ohmmy.app went live, because a link somebody shares is opened on a laptop
   first, and the first impression of the product is a narrow strip in a void.

   WHAT A DESKTOP SCREEN IS FOR, which is the actual question. docs/TODO.md 31
   guessed "the path and the circuit diagram side by side". That guess is
   wrong and it is worth saying why: those two things never share a screen.
   The path is the home screen; a diagram lives inside a question, and a
   question is an overlay covering everything. Putting them side by side would
   mean inventing a state the app does not have.

   What is actually true at 1040px is simpler. The path is a vertical ribbon
   and stays one — reading a list of 36 skills across a metre is worse, not
   better. What does not want to be in that column is the *chrome*: a top bar
   and a tab bar eat vertical space, and on a laptop vertical is the scarce
   axis while horizontal is free. So the chrome moves to a rail on the left,
   where it costs nothing and can finally be read at a glance, and the column
   keeps its reading measure.

   That is the whole idea: same app, chrome to the side, nothing stretched.

   ONE BREAKPOINT, and it is 1040px rather than something smaller. The rail
   plus a real reading column needs about that much before it beats the
   single column, and a tablet in landscape is much happier with the phone
   layout than with a cramped two-pane one. Below this width nothing here
   applies.

   WHAT THIS FILE MUST NOT DO. No transform, filter or perspective on #app or
   anything above it. Any of the three makes an element a containing block for
   position:fixed descendants, and this app has seven fixed overlays; getting
   that wrong is the single most repeated bug in the project's history. The
   overlays are siblings of #app rather than children, which is what makes
   this safe — do not move them in. tests/browser/overlays.spec.js asserts
   both halves of that, at laptop width, at four text sizes. */

@media (min-width: 1040px) {

  /* The ground the card sits on. Without this the column reads as an
     unported phone app; with it, it reads as a page that has decided to be
     narrow. No new colours — the same two surfaces the app already uses. */
  body{
    padding: 32px 0;
    background:
      radial-gradient(120% 90% at 50% 0%, var(--tint) 0%, var(--bg) 62%);
    background-attachment: fixed;
  }

  #app{
    max-width: 940px;
    display: grid;
    grid-template-columns: 244px minmax(0, 1fr);
    /* Explicit rows, because the screens span all of them. Left to implicit
       placement the path is one very tall row and everything else in the rail
       is pushed below it — the level bar landed 2600px down the page. */
    grid-template-rows: auto auto auto 1fr;
    align-items: start;
    column-gap: 28px;
    padding-right: 8px;
    /* The divider is painted rather than a border, so it runs the full height
       of the card instead of stopping where the rail's content happens to
       end. A border on the rail left a line that quit a third of the way
       down, which reads as an unfinished box rather than as two panes. */
    background:
      linear-gradient(var(--line), var(--line)) 244px 0 / 1px 100% no-repeat,
      var(--panel);
  }

  /* ---- the left rail -------------------------------------------------- */

  /* Chrome, level and the ad strip are separate siblings in the markup, so
     each is placed into column one by hand rather than by wrapping them in a
     new element. Wrapping would mean touching index.html for a purely visual
     regrouping, and every overlay's position is measured against that
     structure. */
  #chrome     { grid-column: 1; grid-row: 1; }
  #level-strip{ grid-column: 1; grid-row: 2; }
  .ad-banner  { grid-column: 1; grid-row: 3; }

  #chrome{
    position: sticky;
    top: calc(var(--sat) + 24px);
    border-bottom: 0;
    padding-bottom: 4px;
  }

  /* The bar becomes a header: name above, figures below, both left-aligned.
     On a phone these compete for one line; here they simply do not have to. */
  #topbar{
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 18px 16px 14px;
    border-bottom: 0;
  }
  #stats{
    display: grid;
    grid-template-columns: repeat(2, auto);
    justify-content: start;
    gap: 8px 14px;
  }

  /* The tabs become a list. Same buttons, same order, same active state —
     only the axis changes. */
  #topnav{
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 6px 8px 10px;
    border-top: 0;
  }
  #topnav .nav-btn{
    flex-direction: row;
    justify-content: flex-start;
    gap: 10px;
    padding: 9px 10px;
    border-radius: 9px;
    font-size: 13px;
  }
  #topnav .nav-btn svg{ width: 17px; height: 17px; }
  #topnav .nav-btn.active{ background: var(--tint); }

  /* The rail stays put while the path scrolls under it, and that means all
     three of these, not two. The ad strip was the one left behind — reported
     on 10 September 2026 — and it scrolled 400px off the top of the window
     while the chrome above it held.

     Each is pinned at the slot below the last, which looks like a chain of
     magic numbers and is not quite: the text-size control scales #app, so
     these are lengths in the card's own scaled space and every one of them
     scales with the content above it. Measured at all four text sizes, the
     chrome clears the level strip by 6 to 10px throughout. The slots are
     deliberately a little larger than the boxes they hold, so a name or a
     rank that wraps to a second line has somewhere to go.

     tests/browser/desktop.spec.js scrolls the page at every text size and
     asserts all three are still on screen, which is what actually holds this
     together — if the chain ever stops adding up, that fails rather than
     something quietly sliding away. */
  #level-strip{
    position: sticky;
    top: calc(var(--sat) + 24px + 300px);
    padding: 4px 16px 16px;
  }
  /* "Level 1 · Newcomer" and "0 / 215 XP to Tinkerer" sit on one line on a
     phone, where the bar is 480px wide. In a 244px rail they collide and both
     wrap mid-phrase. Stacked, each gets its own line and neither breaks. */
  #level-strip .lv-top{
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
  #level-strip #goal-row{ flex-wrap: wrap; gap: 4px 8px; }

  .ad-banner{
    position: sticky;
    top: calc(var(--sat) + 24px + 300px + 96px);
    margin: 0 12px 12px;
    border-radius: 10px;
  }

  /* ---- the right column ----------------------------------------------- */

  /* Every screen shares column two. They are display-toggled, never shown at
     once, so they can all be given the same cell. */
  #path-screen,
  #profile-screen,
  #settings-screen,
  #sandbox-screen{
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: stretch;
    padding-top: 26px;
    padding-bottom: 48px;
  }

  /* The reading measure survives the extra room. A path of 36 skills laid
     across 650px is harder to follow than the same path in a column, so the
     width buys margin rather than line length. The sandbox is the exception:
     it is a canvas, and a canvas wants the room. */
  #path-screen > *,
  #profile-screen > *,
  #settings-screen > *{ max-width: 560px; }

  /* ---- overlays ------------------------------------------------------- */

  /* On a phone an overlay is the whole screen, so there is nothing to see
     around it. On a laptop a 680px panel centred in a 1440px window leaves
     the app showing on both sides, half-covered and still looking clickable
     — which is exactly how it looked, and it looked broken.

     So there is a backdrop, and it hangs off body.overlay-open rather than
     off any one overlay. Two reasons. It is the state that already means
     "something is over the app", set in one place and correct for all seven;
     and a pseudo-element of the overlay itself cannot do this job at all —
     #lesson has a z-index, so it is a stacking context, and a z-index:-1
     child paints above its own parent's background rather than behind it.
     The first attempt did exactly that and filled the lesson with grey.

     z-index 39 puts it under #lesson (40) and everything above. The three
     overlays that already carry their own dark background — the ad, the
     confirm dialog, what's-new — simply sit on top of it. */
  body.overlay-open::after{
    content: '';
    position: fixed;
    inset: 0;
    background: rgba(var(--scrim-ink), .45);
    z-index: 39;
  }

  /* Still fixed to the window, still centred, just less like a phone. The
     lesson gets the most because it is the screen with a circuit in it. */
  #lesson   { width: 680px; top: 40px; bottom: 40px; }
  #placement{ width: 620px; top: 40px; bottom: 40px; }
  #lesson, #placement, #mailflow, #gate{
    box-shadow: 0 18px 50px rgba(var(--scrim-ink), .22);
  }

  .l-body, .pl-body{ padding-left: 40px; padding-right: 40px; }

  /* The room the diagram never has on a phone. It is the one thing in a
     lesson that is genuinely better bigger — a schematic squeezed to 300px
     is read by squinting — so it is allowed past the prose measure while the
     words around it are not. */
  .l-body .dia svg{ max-width: 420px !important; }
  .l-body .q-text{ max-width: 560px; }

  /* Options in two columns when they are short enough to stay readable in
     one line each. Four stacked buttons on a wide screen puts the last one a
     long way from the question it answers. */
  .l-body .opt{ margin-bottom: 8px; }
}

/* The signed-out page is the one screen a stranger sees, and it is the one
   most damaged by the phone column: a product's front door 480px wide in a
   1440px window reads as unfinished. It gets the width earlier than the app
   does, because it has no path to keep narrow. */
@media (min-width: 860px) {
  #gate{ padding: 40px 24px; }
  .gate-box{ max-width: 560px; }
}
