/* ==========================================================================
   layout.css — the sky, the canvas, the two columns, the plates.
   No colours are defined here. Tokens only.
   ========================================================================== */

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

/* The sky goes on the ROOT element, not on body. A background on <html>
   propagates to the canvas and paints the whole viewport however short the
   document is; the same gradient on body stops at the body box and leaves
   flat colour under the fold, which is exactly what it did first time. */
html {
  min-height: 100%;
  background:
    linear-gradient(180deg,
      var(--sky-top) 0%,
      var(--pool) 34%,
      var(--sky-low) 68%,
      var(--sky-horizon) 100%) no-repeat 0 0 / 100% 100%,
    var(--pool);
}


/* Clouds ride over the sky, on body, in three layers at different scales.
   They tile in BOTH directions and run the whole depth of the page, not as
   one band near the top. The three tiles are deliberately awkward sizes —
   704, 928, 1216 — so the combined pattern does not visibly repeat over a
   page this long. The one blurred edge in the design: the board's skies are
   airbrushed and everything else here is hard. */
body {
  margin: 0;
  min-height: 100vh;
  padding: 26px 20px 40px;
  background:
    url('/img/skin/sky-near.svg') repeat 0 0,
    url('/img/skin/sky-mid.svg')  repeat 140px 60px,
    url('/img/skin/sky-far.svg')  repeat 40px 220px;
  color: var(--ink);
  font: var(--fs-body)/var(--lh-body) var(--font-ui);
  -webkit-text-size-adjust: 100%;
}

/* The canvas: 940px of content, centred on the tile, in a hard frame.
   300 + 20 + 620 = 940 exactly, so the grid *is* the canvas — which means
   --w-page has to be the content box, with the frame outside it. */
.canvas {
  box-sizing: content-box;
  width: var(--w-page);
  margin: 0 auto;
  padding: var(--gap);
  background: var(--chrome);
  border: 2px solid var(--plate);
  box-shadow:
    inset 1px 1px 0 var(--bevel),
    0 0 0 1px var(--accent);
}

/* align-items: stretch, so the two columns share a height and the character
   panel can reach the bottom of the Top 6.

   The left column is TWO elements on desktop: the rail (display picture and
   Now Playing) in row 1, and the cabinet (the character panel) in row 2.
   The cabinet comes after main in the markup so that on a phone it stacks
   last — see the collapse below — and the grid puts it back here. Main spans
   both rows. Row 1 is the rail's natural height, the row gap is --stack (the
   same 12px the rail's own items sit apart), and row 2 takes whatever is
   left of main's height, so the character panel's top and bottom edges land
   exactly where they did when it was the rail's last item. Diffed at 1440
   and 1024: zero pixels.

   Scoped to html.js because with scripting off the inline albums are
   visible, the main column is several thousand pixels tall, and there is no
   Top 6 bottom edge to align to — the rail should keep its natural height
   in that case. */
.profile {
  display: grid;
  grid-template-columns: var(--w-rail) var(--w-main);
  grid-template-rows: auto 1fr;
  column-gap: var(--gap);
  row-gap: var(--stack);
  align-items: start;
}
.rail    { grid-column: 1; grid-row: 1; }
.main    { grid-column: 2; grid-row: 1 / 3; }
.cabinet { grid-column: 1; grid-row: 2; }

.js .profile { align-items: stretch; }

/* The rail is a column of natural-height items. */
.js .rail {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.js .rail > * { flex: 0 0 auto; }

/* The cabinet is a column too, so the character panel in it can absorb the
   slack down to the bottom of the Top 6. */
.js .cabinet {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* With scripting off the character panel is hidden (components.css), and
   an empty landmark should not be left behind it. */
html:not(.js) .cabinet { display: none; }

.rail > * + *,
.main > * + * { margin-top: var(--stack); }

/* --- Skip link ----------------------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--pad-tight) var(--pad);
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--rule);
  font-size: var(--fs-data);
}
.skip:focus { left: 20px; top: 20px; }

/* --- Site foot -----------------------------------------------------------
   On its own plate. The old footer sat straight on the background and only
   managed 3.9:1, which is a fail — and it is where the only contact link on
   the site lives. A plate fixes it without touching the backdrop.
   -------------------------------------------------------------------------- */

.foot {
  width: var(--w-page);
  margin: var(--gap) auto 0;
  padding: var(--pad-tight) var(--pad);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--gap);
  background: var(--plate);
  border: 1px solid var(--accent);
  color: var(--plate-ink);
  font-size: var(--fs-data);
  letter-spacing: var(--track-data);
}
.foot p { margin: 0; }

/* ==========================================================================
   Responsive collapse. The fixed canvas is the point on desktop —
   it only gives way once it genuinely cannot fit.
   ========================================================================== */

/* 1023, not 999. The fixed canvas needs 940 content + 2x20 padding +
   2x2 border = 984, plus 2x20 body padding = 1024. Collapsing at 999 left
   viewports between 1000 and 1023 with a few pixels of horizontal scroll. */
@media (max-width: 1023px) {
  body { padding: 16px 12px 32px; }

  /* Below the fixed canvas the frame goes back to border-box and fills. */
  .canvas {
    box-sizing: border-box;
    width: 100%;
    max-width: calc(var(--w-page) + 2 * var(--pad-loose));
    padding: var(--pad-loose);
  }
  .foot { width: 100%; max-width: var(--w-page); }

  /* One column, in DOM order: the rail (display picture, Now Playing),
     then main (About, the Top 6), then the cabinet (the character panel)
     last. Kearnan, 9 Oct 2026. No `order` and no `display: contents`: the
     panel is moved in the markup instead, so what is seen and what is read
     or tabbed through are the same sequence, and the <aside> and <main>
     landmarks stay real boxes. The grid placement above does nothing in a
     flex column. The gap is --stack so the three read as one run of
     panels. */
  .profile {
    display: flex;
    flex-direction: column;
    gap: var(--stack);
  }
  /* min-width: 0 is load-bearing. A flex item defaults to min-width: auto,
     so it refuses to be narrower than its widest content — and the attract
     strip's horizontal reel is 1280px of figures. Without this the column
     holding the character panel grew to 1284px and put horizontal scroll
     on a 320px screen, even though the reel itself was clipped and
     invisible. */
  .rail,
  .main,
  .cabinet { min-width: 0; }

  /* The portrait is a 300px column element; unpin it, and centre it in the
     full-width column. */
  .rail > .portrait {
    max-width: 320px;
    margin-left: auto;
    margin-right: auto;
  }
}

@media (max-width: 560px) {
  body { padding: 10px 8px 24px; }
  .canvas { padding: var(--pad); }
  .foot { flex-direction: column; gap: var(--pad-tight); }
}

@media (max-width: 380px) {
  body { padding: 8px 6px 20px; }
  .canvas { padding: var(--pad-tight); }
}
