/* ════════════════════════════════════════════════════════════════════════════
   KORVA — DESKTOP LAYOUT LAYER  (Agent K, Session 7)

   The logged-in app was laid out vertically at every width. On a laptop — the
   screen a parent actually evaluates the product on — that left two thirds of
   the glass empty and made a $29/month product read as thin. This file is the
   ≥1024px answer: a persistent left rail instead of a burger, and multi-column
   arrangements on the surfaces whose content genuinely splits.

   ── RULES OF THIS FILE ───────────────────────────────────────────────────────

   1. EVERY rule lives inside `@media (min-width: 1024px)`. Nothing here can
      reach a phone or a tablet in portrait. The <1024px experience is not
      "mostly preserved" — it is untouched by construction.

   2. It loads LAST (see base.html). style.css collapses the kid nav to a burger
      inside `@media (max-width: 1200px)`; media queries add no specificity, so
      only a later, at-least-as-specific rule can win at 1024–1200. That is why
      this is a separate sheet and not an append to app.css.

   3. NO NEW COLOUR. Every value here is a layout value or an existing token
      from theme.css / style.css. The one new pairing this file introduces is
      the rail surface, and it reuses --surface / --line / --ink*.

   4. THE RAIL IS GATED ON `:has()`. `body:has(> .knav:not(.knav--test):not(.knav--public))` is the
      switch, and it is on EVERY rail rule including the body offset. That is
      deliberate: if a browser does not support `:has()`, the whole selector is
      invalid and every rule drops together, so the page falls back to exactly
      today's sticky top bar rather than to a half-applied layout with content
      sliding under a fixed rail. Three surfaces cannot use a body class
      instead — /privacy, /terms and the admin pages override {% block nav %},
      so a logged-in parent on those pages has the body flag and no nav to go
      with it.

   4b. ⚑ `.knav--public` IS EXCLUDED, AND IT IS THE SAME ACCIDENT P2 FOUND ON
      /login — NOT an intended marketing sidebar. Added Session 8, Agent P3.

      The gate originally excluded `.knav--test` and nothing else, so it also
      matched the marketing nav. Above 1024px `/`, `/pricing` and `/how-it-works`
      therefore shipped a 240px fixed white sidebar plus `padding-left: 240px` on
      <body>. Measured before the fix: nav width 240px, position fixed, body
      padding-left 240px, <main> left edge at 240 and width 1200 at 1440 — and
      identically at 1024 and 1920.

      It is an accident, on five pieces of evidence:

        1. THE RAIL WAS DESIGNED FOR A DIFFERENT NAV. Every worked example in
           this file's header and in section 1 is about the LOGGED-IN kid nav —
           its burger, its section group, its account disclosure, its "Done" CTA.
           The marketing nav has none of those.

        2. THE CONTENT DOES NOT FILL IT. The public nav is three links. A 240px
           persistent rail holding Home / How it works / Pricing leaves roughly
           700px of empty white below them at a 900px viewport.

        3. `.knav-spacer` PROVES THE ORIGINAL INTENT. It exists to push "Log in"
           and "Start free" to the RIGHT of a horizontal bar. In a column it
           pushes them to the bottom of the viewport instead, stranding the
           primary conversion CTA ~700px below the last nav item.

        4. IT TAXED THE PAGE IT SHOULD SERVE. 240px came off the hero at every
           width above 1024, while the same page below 1024 got the full width.

        5. P2 REACHED THE SAME VERDICT INDEPENDENTLY for `.knav--auth` and fixed
           it; static/auth.css records the `.knav--public` case explicitly, as
           unfixed only because changing it was outside a login task.

      The fix is one `:not()` rather than deleting the nav (P2's route), because
      the marketing pages genuinely need theirs — it is the sticky top bar the
      same markup already renders below 1024px, and it is what every rule outside
      this file was written against.

   5. TEST MODE KEEPS THE TOP BAR. `.knav--test` is excluded above. A running
      practice test or mock is a deliberately stripped surface whose only
      control is "Exit test"; giving it a 240px navigation rail would both waste
      the width the exam layout wants and re-open the escape routes test mode
      exists to close.
   ════════════════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) {

  :root {
    /* Rail width. 240 fits "Written expression" and "Weekly Challenge" at the
       nav's own 13.5px Lexend without truncation; 264 above 1440 because the
       gutters grow there and a 240 rail starts to look pinched. */
    --kd-rail: 240px;
    --kd-gap: clamp(20px, 2vw, 32px);
  }

  /* ══════════════════════════════════════════════════════════════════════════
     1. THE RAIL
     ══════════════════════════════════════════════════════════════════════════ */

  body:has(> .knav:not(.knav--test):not(.knav--public)) {
    padding-left: var(--kd-rail);
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) > .knav {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--kd-rail);
    z-index: 140;
    background: var(--surface);
    border-right: 1px solid var(--line);
    backdrop-filter: none;         /* opaque rail; the blur was for a translucent bar */
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) > .knav > .knav-inner {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    flex-wrap: nowrap;
    gap: 18px;
    height: 100%;
    max-width: none;
    width: 100%;
    padding: 22px 14px 20px;
    margin: 0;
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-brand {
    margin: 0 0 2px 6px;
    font-size: 19px;
    align-self: flex-start;
  }

  /* The burger is style.css's answer to a nav that does not fit a row. A column
     always fits, so there is nothing left for it to reveal. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-burger {
    display: none;
  }

  /* Beats `.knav--kid .knav-menu { display:none }` in style.css's
     max-width:1200 block on specificity (0,2,1 vs 0,2,0) AND on source order. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-menu {
    display: flex;
    position: static;
    flex-direction: column;
    align-items: stretch;
    flex: 1 1 auto;
    flex-wrap: nowrap;
    gap: 2px;
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
    max-height: none;
    overflow: visible;
    min-width: 0;
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-group {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
  }

  /* Section group and weekly group each get a hairline above them, so the rail
     reads as three ranks (place · sections · this week) rather than one list. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-group,
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-group--weekly {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--line-soft);
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-link {
    width: 100%;
    justify-content: flex-start;
    padding: 9px 12px;
    font-size: 14px;
    border-radius: var(--r-sm, 10px);
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-link--quiet {
    font-size: 13px;
    padding: 8px 12px;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-link__ico {
    width: 18px;
    text-align: center;
    font-size: 14px;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-soon {
    width: 100%;
    justify-content: space-between;
    padding: 9px 12px;
  }

  /* The spacer is what pushes the account disclosure and Done to the bottom of
     the rail, the same job it did pushing them to the right of the bar. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-spacer {
    display: block;
    flex: 1 1 auto;
    min-height: 12px;
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-more {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--line-soft);
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-who {
    width: 100%;
    justify-content: flex-start;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-who::after { margin-left: auto; }

  /* In a 240px rail an absolutely-positioned popover has nowhere to go but off
     the left edge of the screen, so the disclosure opens in flow instead — the
     same decision style.css already made for the collapsed mobile panel. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-more__panel {
    position: static;
    min-width: 0;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 4px 0 0;
  }

  body:has(> .knav:not(.knav--test):not(.knav--public)) .knav-link--cta {
    margin-top: 10px;
    justify-content: center;
  }

  /* Anything the app fixes to the viewport has to clear the rail. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .toast { left: calc(var(--kd-rail) + 24px); }

  /* ── The split practice surfaces ──────────────────────────────────────────
     style.css splits the stimulus/answer panes from 900px (.q-split--reading,
     .q-split--quant-pack) and 1100px (.q-split, .k-practice--split). Those
     numbers were chosen against the whole viewport; the rail takes 240 of it,
     so the same amount of room now arrives 240px later. Shifting the threshold
     is the honest fix — leaving it would hand a passage a ~330px column at
     1024, which is narrower than any width the split was ever designed for. */
  @media (max-width: 1139px) {
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-split--reading,
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-split--quant-pack {
      display: flex;
      flex-direction: column;
    }
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-split--reading > .q-passage-shell,
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-split--quant-pack > .q-stimulus-shell {
      position: static;
    }
  }
  @media (max-width: 1339px) {
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-split,
    body:has(> .knav:not(.knav--test):not(.knav--public)) .k-practice--split {
      grid-template-columns: minmax(0, 1fr);
    }
    body:has(> .knav:not(.knav--test):not(.knav--public)) .q-passage-shell,
    body:has(> .knav:not(.knav--test):not(.knav--public)) .k-practice__aside {
      position: static;
    }
  }

  /* ══════════════════════════════════════════════════════════════════════════
     2. SHARED TWO-COLUMN PRIMITIVE

     `.kd-cols` wraps two `.kd-col`s. Below 1024 it is not in this file at all,
     so both wrappers are plain blocks and the page renders in DOM order — which
     is why every surface below groups its blocks into CONTIGUOUS runs of the
     existing mobile order. Nothing is reordered; the runs are only placed side
     by side once there is room for two.
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-cols {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: var(--kd-gap);
    align-items: start;
  }
  .kd-col { min-width: 0; }
  .kd-col--side { position: sticky; top: 24px; }

  /* A page that opts into the desktop layout drops the 78ch reading measure
     style.css puts on every direct child of .page-narrow. The measure is right
     for a single column of prose; it is exactly the rule that was letterboxing
     these dashboards. Prose blocks keep their own measure below. */
  .kd-wide > * { max-width: none; margin-left: 0; margin-right: 0; }
  .kd-wide { max-width: 1500px; margin-inline: auto; }

  /* ══════════════════════════════════════════════════════════════════════════
     3. /practice/home — the child's home
     ══════════════════════════════════════════════════════════════════════════ */

  /* Greeting + stat strip share one band instead of stacking. */
  .kd-home__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 24px;
    margin-bottom: 22px;
  }

  /* The section picker gets the full width it always wanted: four tiles across
     rather than two rows of two. */
  .kd-home .ks-sections { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* The closing band: Learn + Recently on the left, Fo's note on the right. */
  .kd-home__tail { align-items: start; }

  /* ══════════════════════════════════════════════════════════════════════════
     4. /dashboard — the parent dashboard
     ══════════════════════════════════════════════════════════════════════════ */

  /* Two sidebars is one too many, and measuring it settled the argument: with
     the rail at 240 and .k-shell__aside at 20vw, .dash-main was 708px at 1440 —
     narrow enough that the skill-mastery labels truncated ("Authorial Choi…").
     So when the rail is present the dashboard's own aside stops being a rail and
     becomes a strip above the children: the child list is a row of chips, the
     account links a row of links. Nothing is removed, and .dash-main gets the
     whole width back. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-shell { grid-template-columns: minmax(0, 1fr); }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-aside {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 20px 28px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--line-soft);
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-nav > .k-eyebrow {
    margin: 0 6px 0 0 !important;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-nav__item { width: auto; }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-aside > .k-rule { display: none; }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-aside__links {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 20px;
    margin-left: auto;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-aside__links .k-btn--block { width: auto; }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-aside__links .k-hint { display: none; }

  /* Each child's card becomes a grid, so a parent sees the week, the mastery,
     the sessions and the skill heat-map together instead of scrolling four
     screens for them. Areas, not auto-flow: the blocks have very different
     heights and auto-placement would leave a ragged hole. */
  @media (min-width: 1280px) {
    .dash-child {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      column-gap: var(--kd-gap);
      /* Cards keep their own height. Stretching them to the row's tallest left a
         200px hole under "This week" and another under "Recent sessions". */
      align-items: start;
      /* ⚑ Agent P3, Session 8 — the pairing changed, the DOM did not.
         MEASURED at 1440 with the old areas: "week | split" paired a 220px block
         with a 430px one, and "sessions | skills" paired a 575px block with a
         110px one, because .kd-dash-skills is a COLLAPSED <details> and
         .kd-dash-sessions is a six-row list. That is 675px of empty card-ground
         inside every child's panel, and there are as many panels as children.

         `split` now spans rows 3-4 and `sessions` spans rows 4-5, which stacks
         220+575 against 430+110 and leaves ~255px. Every area is still a
         rectangle, the DOM order is untouched (week, split, sessions, skills),
         so the visual order still matches the reading order, and below 1280 this
         whole block does not apply — the phone stack is byte-for-byte what it
         was. */
      /* ⚑ SESSION 10, ITEM 12 — FIVE BLOCKS, NOT ELEVEN. `metrics`, `sessions`,
         `skills` and `weeks` no longer exist on this page: the test-ready card,
         the recent-session list, the grouped skill grid and the past-weeks table
         moved to /child/<id>/activity. Their area names and their selectors are
         gone with them rather than left behind pointing at nothing — a
         grid-template-areas entry with no element to fill it reserves a row of
         empty ground, which is the exact defect the Session 8 note below records.

         `split` now spans the full width, so it goes back to its own natural
         1.15fr/0.85fr and the override that stacked it inside one column is
         removed. `week` (four numbers) and `focus` (one skill) are both short and
         pair cleanly on one row. */
      grid-template-areas:
        "head     head"
        "split    split"
        "week     focus"
        "actions  actions";
    }
    .dash-child > .dash-child__head { grid-area: head; }
    .dash-child > .kd-dash-split    { grid-area: split; }
    .dash-child > .kd-dash-week     { grid-area: week; }
    .dash-child > .kd-dash-focus    { grid-area: focus; }
    .dash-child > .dash-child__actions { grid-area: actions; }
  }

  .dash-metrics { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

  /* ══════════════════════════════════════════════════════════════════════════
     5. /section/<id> — the section hub

     Left: what you can DO here (practice, tests, the skill check).
     Right: what you HAVE done here (skills, mistakes, this week).
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-sec .sec-actions { grid-template-columns: minmax(0, 1fr); }
  .kd-sec .sec-test-grid { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
  .kd-sec .kd-col > .sec-block:last-child { margin-bottom: 0; }

  /* ══════════════════════════════════════════════════════════════════════════
     6. /section/<id>/mistakes
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-mistakes .sec-mistakes--full {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
    gap: 14px;
    align-items: start;
  }

  /* ══════════════════════════════════════════════════════════════════════════
     7. /challenge — the Weekly Challenge hub
     ══════════════════════════════════════════════════════════════════════════ */

  /* Scoped to .kd-ch, NOT to .ch-hub: challenge_walkthrough.html uses .ch-hub too
     and is long-form prose, which 1180px would set at an unreadable measure. */
  .kd-ch { max-width: 1180px; }
  .kd-ch .ch-sections { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  @media (min-width: 1440px) {
    .kd-ch .ch-sections { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }

  /* ══════════════════════════════════════════════════════════════════════════
     8. /mocks — the Weekly Mock hub
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-mock { max-width: 1180px; }
  .kd-mock .mock-sections { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .kd-mock .mock-facts { justify-content: flex-start; gap: 28px; }
  /* Long review tables and prose stay narrower than the hub grids. */
  .kd-mock--read { max-width: 1040px; }

  /* ══════════════════════════════════════════════════════════════════════════
     8b. Practice-test results — width, not columns. "Every question" is a
     disclosure list and reads worse in two columns; only the skill bars pair up.
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-results { max-width: 1080px; margin-inline: auto; }
  .kd-results > * { max-width: none; margin-left: 0; margin-right: 0; }
  .kd-results .sec-skills {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 28px;
  }

  /* ══════════════════════════════════════════════════════════════════════════
     9. /child/<id>/activity — the parent's per-child history
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-act .kd-cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
  .kd-act .skill-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

  /* ══════════════════════════════════════════════════════════════════════════
     10. /practice (child picker) and /settings
     ══════════════════════════════════════════════════════════════════════════ */

  .kd-picker { max-width: 900px; margin-inline: auto; }
  .kd-picker > * { max-width: none; }
  .kd-picker .stack {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 18px;
  }

  /* Width only. .row keeps its Session-6 `flex-wrap: wrap` — forcing nowrap here
     to guarantee one line is exactly the trade that put /settings 4px past the
     viewport at 375. At 1180 the row fits without being told to. */
  .kd-settings { max-width: 1180px; margin-inline: auto; }
}


/* ════════════════════════════════════════════════════════════════════════════
   /dashboard — THE CHILD ROW AND THE CHILD BLOCK ACTUALLY LINE UP
   Session 10b, Agent U3.  Everything here is MEASURED; the numbers are the
   before/after of a real render at 1024 / 1440 / 1920.

   ── 1. THE CHILDREN STRIP WAS NEVER A ROW ───────────────────────────────────
   ⚑ THE BUG IS ONE MISSING DECLARATION AND IT HAD BEEN SHIPPING SINCE THE STRIP
   WAS WRITTEN.  The block above turns .dash-aside into a horizontal band and its
   own comment says "the child list is a row of chips" — but it set only
   `display: flex; flex-wrap: wrap; align-items: center; gap` on .dash-nav and
   never touched `flex-direction`, so style.css:3729's `.dash-nav { flex-direction:
   column }` still applied.  Computed flex-flow read `column wrap`.  The children
   stacked, and because a wrapping COLUMN centres its lines under `align-items:
   center`, each row was centred on its own width — so a child whose XP string is
   one glyph longer pushed its own name sideways:

       width   Arjun name .left   Maya name .left   offset
       1024        340.95            343.27         2.32px
       1440        386.39            388.70         2.31px
       1920        434.39            436.70         2.31px
   and the two "Start practising" buttons drifted the OTHER way by 2.33px, so the
   error between the name and its own button was ~4.6px.

   ⚑ THE FIX IS `align-items: stretch`, NOT `flex-direction: row`, AND THAT WAS
   MEASURED TOO.  Making the strip a genuine row was tried first, because that is
   what the comment above promises.  Rendered, it truncated: at 1024 the band is
   702px, two chips at their natural ~296px plus the "Children" label plus the
   account links do not fit, and the flex algorithm took the difference out of
   `.dash-nav__item` (min-width: 0) — "Arjun" measured 42.83px wide before and
   40.50px after, i.e. the name was being clipped to buy the layout, and at 1920
   the second chip wrapped to its own line LEFT of the first.  Stretch keeps the
   lines stacked and gives them one width instead, which is what actually puts
   the names on one vertical axis: 0.00px offset by construction, whatever the
   names and XP numbers are, and with no width for a third child to overflow.

   ── 2. ONE CHILD BLOCK, ONE PAIR OF COLUMNS ─────────────────────────────────
   ⚑ THE BLOCK WAS TWO DIFFERENT GRIDS STACKED.  `.dash-child` is
   `1fr 1fr` with `column-gap: var(--kd-gap)`, but the `split` row is its own
   `.ks-split` grid at `1.15fr 0.85fr` with a hard 34px (18px as rendered) gap.
   Two rows of cards, two different column boundaries, measured at 1440:

       row              left card            right card           boundary
       split            326.39 -  906.69     924.69 - 1353.61      906.69
       week | focus     326.39 -  825.59     854.39 - 1353.61      825.59
   an 81.1px disagreement at 1440 and 111.5px at 1920, plus two different gaps
   (18.0 vs 28.8).  The split now inherits the block's own columns and the block
   has ONE vertical rule down its middle.

   ⚑ THE 1.15/0.85 RATIO IS NOT PRESERVED AND THAT IS THE POINT.  It was chosen
   when the split shared a column with something else; it now spans the full
   width beside a 1fr/1fr row, and a ratio nobody can see the reason for is
   exactly what made the block look broken.  `.ks-split` is UNCHANGED for every
   other page that uses it — this is scoped to `.dash-child`.

   ── 3. THE PANEL CTA SITS ON THE COLUMN EDGE ────────────────────────────────
   `.dash-child__go` followed the <h2> in normal flow, so its left edge was the
   name's width plus a gap — 424.55 for "Arjun" and 426.63 for "Maya" at 1440,
   and any nickname would move it further.  It is pushed to the row's end, which
   is the block's right edge, which is the same edge the cards below it end on.
   Both children: one x, and it cannot drift.

   ⚑ NOT DONE ABOVE 1024 ONLY BY ACCIDENT.  Below 1024 the panel is a single
   narrow column and style.css:3834 already gives this button the full width;
   pushing it right there would leave a gap beside a name instead.
   ════════════════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) {
  /* THE FIX: the lines share one width, so a longer name or a longer XP string
     can no longer move its own row sideways.  `align-items: center` was
     shrink-wrapping and then CENTRING each line; `stretch` makes every line the
     width of the widest, which is what puts the names on one vertical axis and
     the buttons on another.  align-self on the row rather than a width, so a
     third or fourth child on a legacy account joins the same two axes. */
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-nav {
    align-items: stretch;
  }
  body:has(> .knav:not(.knav--test):not(.knav--public)) .dash-nav > .k-eyebrow {
    align-self: center;
  }

  /* One pair of columns per child block, at every width the block has two. */
  .dash-child > .kd-dash-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--kd-gap);
  }

  .dash-child__ident { flex: 1 1 auto; }
  .dash-child__namerow { width: 100%; }
  .dash-child__go { margin-left: auto; }
}
