/* =====================================================================
   JOURNAL — the homepage's editorial block.

   Two columns that are exactly the same height: one big story on the left
   that rotates on its own, and a "This Just In" stack of newer pieces on
   the right.

   The symmetry is structural, not eyeballed:

     • Both columns are grid children of one row, so they stretch to a
       common height by definition — neither can drift as copy changes.
     • Every slide in the left column shares one grid cell, so the stage is
       always as tall as the tallest slide and NEVER resizes mid-rotation.
       (Absolutely-positioned slides would collapse the stage to nothing;
       a stack that swaps `display` would make the block jump on every
       tick. One cell, crossfaded, does neither.)
     • The right list is a flex column of `flex: 1 0 auto` rows, so however
       many stories it holds they divide that same height evenly and the
       last hairline lands flush with the bottom of the photo column.

   Headlines are line-clamped rather than left to run, which is what keeps
   the two halves honest — an unusually long title changes nothing about
   the height of anything, and no row can outgrow its share.
   ===================================================================== */
.kjrn {
  --kj-ink: #213857;
  --kj-sub: rgba(33, 56, 87, .62);
  --kj-line: rgba(33, 56, 87, .16);
  --kj-rule: #2e4755;          /* the heavy bar under "This Just In" */
  --kj-accent: #BD830D;        /* focus rings, hover underline       */
  --kj-ease: cubic-bezier(.22, .61, .36, 1);
  /* A serif for the display headline only. The reference sets its lead
     story in one, and it is the single strongest cue that this band is the
     magazine part of the page rather than another product rail. Kept to a
     system stack so it costs no font request. */
  --kj-serif: 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia,
              'Times New Roman', serif;

  display: block;
  padding: clamp(30px, 3.4vw, 54px) 0;
  background: transparent;
  color: var(--kj-ink);

  /* The breakpoints below are container queries, not media queries, because
     the viewport is not what this section is laid out in: the homepage keeps
     a 200px sidebar on desktop, so a 1100px window leaves the row about 900px
     to work with. Asking the window would put two columns into that 900px and
     squeeze the list until its rows collided with their own dividers. Asking
     the section gets the real answer at any window size, sidebar or not. */
  container-type: inline-size;
  container-name: kjrn;
}

/* --------------------------------------------------------------- the row
   Roughly 5:3. Wide enough that the lead photograph reads as a lead, narrow
   enough that the right column still fits a headline on two lines beside its
   thumbnail. `minmax(0, …)` on both tracks so a long unbroken word can never
   push a column past its share. */
.kjrn__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.66fr) minmax(0, 1fr);
  column-gap: clamp(24px, 3.2vw, 56px);
  align-items: stretch;
}

/* =============================================================== LEFT
   The lead story.

   A column that fills its grid row, so the dots come to rest on the row's
   floor. Stretching the box alone was not enough: the row is as tall as the
   taller of the two columns, and when that was the story list the stage kept
   its natural height and left the difference as dead space under the dots —
   the two halves ended on visibly different lines. Passing the stretch down
   (stage → slides → caption) hands that slack to the caption, which is the
   one part built to absorb it. */
.kjrn__stage {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.kjrn__slides {
  display: grid;
  /* Every slide claims the same cell. The track therefore measures the
     tallest of them once and holds that height for good. */
  grid-template-areas: 'slide';
  flex: 1 1 auto;
  min-height: 0;
}
.kjrn__slide {
  grid-area: slide;
  min-width: 0;
  /* A column, so the caption can take the slack. The cell is as tall as the
     longest headline in the set; a slide with a shorter one would otherwise
     hang from the top of it with the difference dumped underneath. */
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transition: opacity .55s var(--kj-ease), visibility 0s linear .55s;
}
.kjrn__slide.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity .55s var(--kj-ease), visibility 0s;
}

/* The photograph. A fixed ratio, so the stage's height is decided by the
   caption alone and the image can never be the thing that shifts. */
.kjrn__shot {
  position: relative;
  display: block;
  aspect-ratio: 19 / 10;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(33, 56, 87, .07);
}
.kjrn__shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 6s linear;
}
/* A very slow drift on the live slide, so a stage that changes only every
   few seconds is not completely static in between. */
.kjrn__slide.is-on .kjrn__shot img { transform: scale(1.035); }

/* ------------------------------------------------------------ the caption
   Three columns — arrow, words, arrow — rather than two arrows floated over
   the text. The words therefore sit in a track that is the same distance
   from both edges whatever the arrows do, and nothing overlaps at any
   width. */
.kjrn__cap {
  display: grid;
  grid-template-columns: clamp(30px, 3cqw, 46px) minmax(0, 1fr) clamp(30px, 3cqw, 46px);
  align-items: center;
  column-gap: clamp(6px, 1vw, 16px);
  padding-top: clamp(14px, 1.6vw, 22px);
  /* Takes the slack the slide left it, and centres the words in it — so a
     one-line headline is set in the middle of the space a three-line one
     would have used rather than leaving a hole beneath itself. The arrows
     ride along, staying level with the headline either way. */
  flex: 1 1 auto;
  align-content: center;
}
.kjrn__capTxt {
  grid-column: 2;
  min-width: 0;
  text-align: center;
}

.kjrn__eyebrow {
  display: block;
  margin: 0 0 clamp(6px, .7vw, 10px);
  font-size: clamp(.66rem, .76vw, .74rem);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--kj-rule);
}

.kjrn__title {
  margin: 0;
  font-family: var(--kj-serif);
  font-weight: 600;
  font-size: clamp(1.35rem, 2.25cqw, 2.3rem);
  line-height: 1.22;
  letter-spacing: -.005em;
  /* Three lines is the ceiling. There is no floor to match it, and none is
     needed: the slides share one grid cell, so the stage is already fixed at
     the height of the longest headline in the set and a short one cannot
     shrink it. A floor here would only pad every caption to three lines. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.kjrn__title a {
  color: var(--kj-ink);
  text-decoration: none;
  transition: color .2s var(--kj-ease);
}
.kjrn__title a:hover { text-decoration: underline; text-underline-offset: 3px; }

.kjrn__by {
  margin: clamp(8px, 1vw, 14px) 0 0;
  font-size: clamp(.75rem, .86vw, .85rem);
  color: var(--kj-sub);
}

/* ------------------------------------------------------------- the arrows
   Bare glyphs, as the reference has them — no button chrome to unbalance
   the two sides of the headline. */
.kjrn__arrow {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--kj-rule);
  cursor: pointer;
  transition: background-color .18s var(--kj-ease), transform .18s var(--kj-ease);
}
.kjrn__arrow:first-child { grid-column: 1; }
.kjrn__arrow:last-child  { grid-column: 3; }
.kjrn__arrow svg { width: clamp(18px, 1.7vw, 26px); height: clamp(18px, 1.7vw, 26px); }
.kjrn__arrow:hover { background: rgba(33, 56, 87, .07); }
.kjrn__arrow:focus-visible { outline: 2px solid var(--kj-accent); outline-offset: 2px; }

/* --------------------------------------------------------------- the dots */
.kjrn__dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  padding-top: clamp(12px, 1.4vw, 18px);
}
.kjrn__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(33, 56, 87, .26);
  cursor: pointer;
  transition: background-color .22s var(--kj-ease), transform .22s var(--kj-ease);
}
.kjrn__dot.is-on { background: var(--kj-rule); transform: scale(1.25); }
.kjrn__dot:focus-visible { outline: 2px solid var(--kj-accent); outline-offset: 3px; }

/* ============================================================== RIGHT
   "This Just In" — a scrolling list, capped to the height of the photo
   column beside it.

   The cap is the whole difficulty. A grid row is as tall as its tallest
   item, so an aside holding twenty stories would simply make the row twenty
   stories tall and there would be nothing to scroll. The fix is to give the
   cell no in-flow content at all: `.kjrn__side` is an empty positioned box,
   so the row is measured from the photo column alone, and the aside fills
   that row from the outside of the sizing calculation. The two columns stay
   exactly level, and everything past the fold becomes scrollable rather
   than either squashed or dropped. */
.kjrn__side {
  position: relative;
  min-width: 0;
}

.kjrn__aside {
  position: absolute;
  inset: 0;
  display: grid;
  /* Heading takes what it needs; the scroller takes the rest — which is
     whatever the photo column ended up being. */
  grid-template-rows: auto minmax(0, 1fr);
  min-width: 0;
}

/* ------------------------------------------------------------ the scroller */
.kjrn__scroll {
  overflow-y: auto;
  /* Without this a grid item refuses to shrink below its content, and the
     list would overflow the panel instead of scrolling inside it. */
  min-height: 0;
  /* Reaching the end of the list carries on down the page, which is what a
     reader flicking through on a phone expects; `contain` here would make
     the panel a dead end. */
  overscroll-behavior-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(33, 56, 87, .28) transparent;
}
.kjrn__scroll:focus-visible { outline: 2px solid var(--kj-accent); outline-offset: 2px; }

/* WebKit wants the parts named individually; Firefox is served by the two
   `scrollbar-*` properties above. Slim and quiet either way — the bar is a
   hint that there is more, not furniture. */
.kjrn__scroll::-webkit-scrollbar { width: 6px; }
.kjrn__scroll::-webkit-scrollbar-track { background: transparent; }
.kjrn__scroll::-webkit-scrollbar-thumb {
  border-radius: 999px;
  background: rgba(33, 56, 87, .26);
}
.kjrn__scroll::-webkit-scrollbar-thumb:hover { background: rgba(33, 56, 87, .42); }

/* A story cut off by the bottom edge is the clearest possible sign that the
   panel scrolls, so the last one is faded rather than sliced. The classes
   are set by the script: no fade at whichever end you have reached, so the
   first and last stories are never dimmed for no reason. A panel whose
   content fits gets neither. */
.kjrn__scroll {
  --kj-fade: 26px;
  mask-image: linear-gradient(to bottom,
    transparent 0, #000 var(--kj-fade),
    #000 calc(100% - var(--kj-fade)), transparent 100%);
}
.kjrn__scroll.at-top    { mask-image: linear-gradient(to bottom, #000 calc(100% - var(--kj-fade)), transparent 100%); }
.kjrn__scroll.at-end    { mask-image: linear-gradient(to bottom, transparent 0, #000 var(--kj-fade)); }
.kjrn__scroll.is-static { mask-image: none; }

.kjrn__asideTitle {
  margin: 0;
  padding-bottom: clamp(8px, .9vw, 12px);
  border-bottom: 3px solid var(--kj-rule);
  font-size: clamp(.92rem, 1.15vw, 1.15rem);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--kj-ink);
}

.kjrn__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  /* At least as tall as the panel, and taller whenever the stories need it.
     That one line is what lets the list behave correctly in both directions:
     a short list stretches to the floor, so its rows (which may grow) divide
     the column evenly and the stack ends flush with the photograph opposite
     instead of trailing off into dead space; a long one runs past the panel
     and scrolls. */
  min-height: 100%;
}
/* `1 0 auto`: a row takes a share of any spare height, but never less than
   its own contents. Rows that could be compressed used to crush each other
   as soon as there were more than about four, which is why the list had to
   be capped at what fit. With the panel scrolling, the floor is what matters
   — past a certain number of stories the rows simply keep their natural
   height, the list outgrows the panel, and the reader scrolls. */
.kjrn__item {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--kj-line);
}
/* Nothing follows the last story, so its rule would be a line drawn under
   the end of the list against the foot of the photograph opposite. */
.kjrn__item:last-child { border-bottom: 0; }

.kjrn__link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(64px, 6cqw, 92px);
  align-items: center;
  column-gap: clamp(10px, 1.2vw, 18px);
  width: 100%;
  padding: clamp(8px, .9vw, 14px) 0;
  text-decoration: none;
  color: inherit;
}

.kjrn__itemTxt { min-width: 0; }

/* Two lines, not three. This is what keeps a row inside the share the flex
   column gave it: eyebrow, two lines and a byline come to a little under the
   height of a quarter of the photo column, at every width the two-column
   layout is used. A third line would push past it and un-level the row. */
.kjrn__itemName {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: clamp(.82rem, .95vw, .95rem);
  font-weight: 600;
  line-height: 1.35;
  color: var(--kj-ink);
}
.kjrn__link:hover .kjrn__itemName { text-decoration: underline; text-underline-offset: 2px; }
.kjrn__link:focus-visible { outline: 2px solid var(--kj-accent); outline-offset: 2px; }

.kjrn__itemBy {
  display: block;
  margin-top: 5px;
  font-size: clamp(.7rem, .8vw, .78rem);
  color: var(--kj-sub);
}

/* Landscape, per the reference, and the same box at every row — the column
   track fixes the width and the ratio fixes the height, so the right edge of
   the stack is a straight line whatever the headlines beside it do. */
.kjrn__itemThumb {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 3px;
  background: rgba(33, 56, 87, .07);
}
.kjrn__itemThumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .45s var(--kj-ease);
}
.kjrn__link:hover .kjrn__itemThumb img { transform: scale(1.06); }

/* ------------------------------------------------------------------ solo
   Fewer stories than the split needs. The lead runs the full width on its
   own rather than sitting beside an empty column. */
.kjrn--solo .kjrn__grid { grid-template-columns: minmax(0, 1fr); }
.kjrn--solo .kjrn__stage { max-width: 860px; margin-inline: auto; }

/* ------------------------------------------------------------ dark theme */
:root[data-theme="dark"] .kjrn {
  --kj-ink: #FAF8F3;
  --kj-sub: rgba(250, 248, 243, .64);
  --kj-line: rgba(250, 248, 243, .2);
  --kj-rule: #E8D8B0;
}
:root[data-theme="dark"] .kjrn__arrow:hover { background: rgba(250, 248, 243, .1); }
:root[data-theme="dark"] .kjrn__dot { background: rgba(250, 248, 243, .3); }
:root[data-theme="dark"] .kjrn__scroll { scrollbar-color: rgba(250, 248, 243, .3) transparent; }
:root[data-theme="dark"] .kjrn__scroll::-webkit-scrollbar-thumb { background: rgba(250, 248, 243, .28); }
:root[data-theme="dark"] .kjrn__scroll::-webkit-scrollbar-thumb:hover { background: rgba(250, 248, 243, .45); }
:root[data-theme="dark"] .kjrn__shot,
:root[data-theme="dark"] .kjrn__itemThumb { background: rgba(250, 248, 243, .08); }

/* ------------------------------------------------------------ responsive */
@container kjrn (max-width: 1080px) {
  /* Nearer to even — below this the 5:3 split starves the right column. */
  .kjrn__grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
  .kjrn__title { font-size: clamp(1.2rem, 2.6cqw, 1.7rem); }
}

@container kjrn (max-width: 860px) {
  /* Stacked. The two halves are no longer side by side, so there is nothing
     left to keep level: the list goes back to sizing to its own copy. */
  .kjrn__grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(26px, 4vw, 40px);
  }
  /* Back into the flow. Stacked, there is no photo column beside the list to
     match, so nothing needs capping — and a panel that scrolls inside a page
     that scrolls is a trap on a touchscreen. The list simply runs to its full
     length and the page carries it. */
  .kjrn__side { position: static; }
  .kjrn__aside { position: static; grid-template-rows: auto auto; }
  .kjrn__scroll {
    overflow: visible;
    mask-image: none;
  }
  .kjrn__scroll[tabindex] { outline: none; }
  /* No panel to fill and no spare height to divide, so the list and its rows
     go back to sizing to their own copy. */
  .kjrn__list { min-height: 0; }
  .kjrn__item { flex: 0 0 auto; }
  .kjrn__item:last-child { border-bottom: 1px solid var(--kj-line); }
  .kjrn__link {
    padding: clamp(12px, 2.4vw, 16px) 0;
    /* A full-width row dwarfs the thumbnail the two-column layout wants, so
       it grows to stay a picture rather than a stamp. */
    grid-template-columns: minmax(0, 1fr) clamp(72px, 12cqw, 118px);
  }
  /* The room is there now, so a long headline gets its third line back. */
  .kjrn__itemName { -webkit-line-clamp: 3; }
}

@container kjrn (max-width: 520px) {
  .kjrn__shot { aspect-ratio: 3 / 2; }
  .kjrn__cap { grid-template-columns: 30px minmax(0, 1fr) 30px; }
}

/* Someone who has asked for less movement gets no crossfade and no drift.
   The rotation itself is stopped in the script. */
@media (prefers-reduced-motion: reduce) {
  .kjrn__slide { transition: none; }
  .kjrn__slide.is-on .kjrn__shot img { transform: none; }
  .kjrn__shot img { transition: none; }
}

/* "View all articles" rides the right end of the "This Just In" rule. */
.kjrn__asideTitle { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.kjrn__all {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: #BD830D;
  text-decoration: none;
  white-space: nowrap;
}
.kjrn__all:hover { text-decoration: underline; }
