/* Nextstep4u — the signed-in app shell.
 *
 * Header, exam switcher, search, notifications, the left rail, and the phone
 * tab bar that replaces the rail. Built from the Claude Design artboard the
 * owner supplied: same structure, same proportions, same behaviour.
 *
 * TWO THINGS WERE TRANSLATED RATHER THAN COPIED, and both are deliberate.
 *
 * COLOUR. The artboard names its own hexes — a blue, four greys, an amber
 * pair. Every one of them is within a few points of a colour this site
 * already has, and scripts/check-palette.py refuses a hex that is not in the
 * canvas file. So each is mapped to the token it is nearest: the artboard's
 * blue to --blue, its page grey to --shell, its hairline to --line, its
 * premium amber to the --amber family. Nothing is approximated by eye twice;
 * the mapping is written down in the runbook.
 *
 * ICONS. The artboard calls for Material Symbols Rounded. That is a third
 * font file on a page that loads two, for an audience on a congested 4G cell,
 * and ADR 0003 allows exactly two faces. The icons are drawn as inline SVG
 * instead — same glyph meanings, no extra request, and they inherit colour
 * from the row they sit in.
 *
 * Sits on top of app.css for tokens, reset and type. Prefixed `ds-`.
 */

/* ── frame ──────────────────────────────────────────────────────────────
   The shell is a fixed header over a two-column body. The rail scrolls on
   its own, so a long nav never drags the page with it. */

.ds-shell{ display:flex; flex-direction:column; min-height:100vh; }
.ds-body{ flex:1; display:flex; min-height:0; }

.ds-main{
  flex:1; min-width:0; background:var(--shell);
  padding:26px 28px 72px;
}
@media (max-width:1100px){ .ds-main{ padding:22px 20px 72px; } }
@media (max-width:560px){ .ds-main{ padding:18px 16px 96px; } }

/* ── header ─────────────────────────────────────────────────────────── */

.ds-head{
  position:sticky; top:0; z-index:30; flex:none;
  height:64px; display:flex; align-items:center; gap:14px;
  padding:0 20px 0 18px;
  background:var(--page); border-bottom:1px solid var(--line);
}
@media (max-width:560px){ .ds-head{ height:56px; padding:0 12px; gap:10px; } }

.ds-logo{ display:flex; align-items:center; cursor:pointer; flex:none; }
.ds-logo img{ height:38px; width:auto; display:block; }
.ds-logo-text{ font-weight:800; letter-spacing:-.02em; font-size:1.05rem; color:var(--ink); }
.ds-logo-text span{ color:var(--blue); }
@media (max-width:560px){ .ds-logo img{ height:30px; } }

.ds-grow{ flex:1; }

/* ── the exam switcher ──────────────────────────────────────────────────
   The artboard puts this next to the logo, and it earns the spot: the whole
   product is "which exam am I preparing for", and the answer decides what
   every other screen shows. The note at the foot of the panel is the one
   thing somebody needs to know before switching — their record does not
   follow them across exams. */

.ds-pop{ position:relative; flex:none; }

.ds-exam-btn{
  display:flex; align-items:center; gap:10px; height:42px;
  padding:0 10px 0 12px; border:1px solid var(--line-3); border-radius:var(--r-md);
  background:var(--page); cursor:pointer; font:inherit;
  transition:background .16s var(--ease), border-color .16s var(--ease);
}
.ds-exam-btn:hover{ background:var(--sunk); }
.ds-exam-txt{ display:block; text-align:left; min-width:0; }
.ds-exam-lab{
  display:block;
  font-size:.625rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); line-height:1;
}
.ds-exam-name{ display:block; font-size:.875rem; font-weight:800; margin-top:4px; line-height:1; color:var(--ink); white-space:nowrap; }
.ds-caret{ color:var(--ink-3); flex:none; transition:transform .2s var(--ease); }
.ds-pop.open .ds-caret{ transform:rotate(180deg); }
.ds-exam-short{ display:none; font-size:.82rem; font-weight:800; color:var(--ink); white-space:nowrap; }
@media (max-width:860px){
  .ds-exam-btn{ padding:0 8px 0 11px; gap:6px; }
  .ds-exam-txt{ display:none !important; }
  .ds-exam-short{ display:block; }
}

/* One panel style for all three dropdowns. */
.ds-panel{
  position:absolute; top:50px; left:0; width:310px;
  background:var(--page); border:1px solid var(--line); border-radius:14px;
  box-shadow:0 16px 40px rgba(13,20,32,.12); padding:8px; z-index:40;
  opacity:0; visibility:hidden; transform:translateY(-6px) scale(.985);
  transform-origin:0 0;
  transition:opacity .16s var(--ease), transform .2s var(--spring), visibility .16s;
}
.ds-panel-right{ left:auto; right:0; transform-origin:100% 0; }
.ds-pop.open .ds-panel{ opacity:1; visibility:visible; transform:none; }

.ds-panel-lab{
  font-size:.69rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); padding:8px 10px 6px;
}
.ds-panel-foot{
  border-top:1px solid var(--line-2); margin-top:6px; padding:10px 10px 4px;
  font-size:.75rem; line-height:1.5; color:var(--ink-3);
}

.ds-row{
  display:flex; align-items:center; gap:12px; width:100%;
  padding:10px; border:0; border-radius:var(--r-md); background:none;
  font:inherit; text-align:left; text-decoration:none; cursor:pointer;
  transition:background .14s var(--ease);
}
.ds-row:hover{ background:var(--chip); }
.ds-row[aria-disabled="true"]{ cursor:default; }
.ds-row[aria-disabled="true"]:hover{ background:none; }
.ds-row-code{
  width:36px; height:36px; border-radius:9px; flex:none;
  display:grid; place-items:center; font-size:.75rem; font-weight:800;
  background:var(--blue-bg); color:var(--blue-deep);
}
.ds-row-code-off{ background:var(--chip); color:var(--ink-3); }
.ds-row-main{ flex:1; min-width:0; display:block; }
.ds-row-name{ display:block; font-size:.875rem; font-weight:700; color:var(--ink); }
.ds-row-sub{ display:block; font-size:.75rem; color:var(--ink-3); margin-top:2px; line-height:1.4; }
.ds-row-tick{ color:var(--blue); flex:none; }

/* ── search ─────────────────────────────────────────────────────────────
   It jumps between the screens this account can open. It does NOT search
   questions or topics: nothing on the server answers that yet, and a box
   that takes a query and shrugs is worse than one that is honest about its
   job. The placeholder says what it does. */

.ds-search{
  flex:1; min-width:120px; max-width:460px;
  display:flex; align-items:center; gap:8px; height:42px; padding:0 12px;
  border-radius:var(--r-md); background:var(--chip); margin-left:6px;
  border:1px solid transparent;
  transition:border-color .16s var(--ease), background .16s var(--ease);
}
.ds-search:focus-within{ background:var(--page); border-color:var(--blue-line); }
.ds-search svg{ color:var(--ink-3); flex:none; }
.ds-search input{
  flex:1; min-width:0; border:0; outline:none; background:transparent;
  font:inherit; font-size:.875rem; color:var(--ink);
}
.ds-kbd{
  font-size:.69rem; font-weight:700; color:var(--ink-3);
  border:1px solid var(--line-3); border-radius:6px; padding:2px 6px;
  background:var(--page); white-space:nowrap; flex:none;
}
@media (max-width:1100px){ .ds-search{ display:none; } }

.ds-results{ max-height:330px; overflow-y:auto; }
.ds-results .ds-row-name mark{ background:var(--amber-bg); color:var(--ink); border-radius:3px; }
.ds-empty{ padding:14px 10px; font-size:.82rem; line-height:1.55; color:var(--ink-3); }

/* ── bell, premium, profile ─────────────────────────────────────────── */

.ds-icon-btn{
  width:42px; height:42px; border-radius:var(--r-md); flex:none;
  border:1px solid var(--line-3); background:var(--page);
  display:grid; place-items:center; cursor:pointer; position:relative;
  color:var(--ink-2);
  transition:background .16s var(--ease);
}
.ds-icon-btn:hover{ background:var(--sunk); }
.ds-dot{
  position:absolute; top:8px; right:9px; width:9px; height:9px; border-radius:50%;
  background:var(--red); border:2px solid var(--page);
}

.ds-premium{
  display:flex; align-items:center; gap:6px; height:32px;
  padding:0 12px 0 9px; border-radius:999px; flex:none;
  background:var(--amber-bg); color:#8A6200; border:1px solid var(--amber-line);
  font-size:.75rem; font-weight:800; cursor:pointer; text-decoration:none;
  transition:background .16s var(--ease);
}
.ds-premium:hover{ background:var(--amber-tint); }
.ds-premium svg{ color:var(--amber-ink); flex:none; }
@media (max-width:860px){ .ds-premium span{ display:none; } .ds-premium{ padding:0 9px; } }

.ds-me{ display:flex; align-items:center; gap:10px; border:0; background:none; padding:0; cursor:pointer; flex:none; font:inherit; }
.ds-av{
  width:38px; height:38px; border-radius:50%; flex:none;
  background:var(--blue-bg); color:var(--blue-deep);
  display:grid; place-items:center; font-size:.8rem; font-weight:800;
}
.ds-me-txt{ display:block; text-align:left; line-height:1.2; min-width:0; }
.ds-me-name{ display:block; font-size:.81rem; font-weight:700; color:var(--ink); max-width:14ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ds-me-sub{ display:block; font-size:.75rem; color:var(--ink-3); max-width:14ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* The avatar alone: the name and address are in the menu it opens. */
.ds-me-txt{ display:none; }

.ds-signout{ color:var(--red) !important; }
.ds-signout:hover{ background:var(--red-bg) !important; }

/* The invisible sheet that closes whichever panel is open when you click
   anywhere else. Under the panels, over everything else. */
.ds-scrim{ position:fixed; inset:0; z-index:25; }

/* ── the rail ───────────────────────────────────────────────────────── */

.ds-rail{
  width:252px; flex:none; background:var(--page);
  border-right:1px solid var(--line);
  overflow-y:auto; overflow-x:hidden;
  padding:14px 12px 28px;
  display:flex; flex-direction:column; gap:16px;
  position:sticky; top:64px; height:calc(100vh - 64px);
  transition:width .18s var(--ease), padding .18s var(--ease);
}
@media (max-width:1100px){ .ds-rail{ width:72px; padding:14px 10px 28px; } }
/* Folded by the owner's button: the same compact rail the 1100px breakpoint
   gives, at any width. */
.ds-mini .ds-rail{ width:72px; padding:14px 10px 28px; }

/* Folded, it opens while the pointer is over it, the way Claude's sidebar
   does, and folds again when the pointer leaves. It opens OVER the page: the
   negative margin keeps its place in the layout at 72px, so nothing on the
   page moves. A short delay stops a pointer passing by from opening it. */
@media (hover:hover) and (min-width:861px){
  .ds-mini .ds-rail:hover{
    width:252px; margin-right:-180px; padding:14px 12px 28px;
    z-index:30; box-shadow:var(--shadow-2); transition-delay:.12s;
  }
}
@media (hover:hover) and (min-width:861px) and (max-width:1100px){
  .ds-rail:hover{
    width:252px; margin-right:-180px; padding:14px 12px 28px;
    z-index:30; box-shadow:var(--shadow-2); transition-delay:.12s;
  }
}
@media (prefers-reduced-motion:reduce){ .ds-rail{ transition:none; } }

/* Account sits at the foot of the rail, apart from the study sections. */
.ds-rail > .ds-grp:last-child{ margin-top:auto; }

/* The fold button. Hidden where the rail is compact anyway. */
.ds-fold{
  display:flex; align-items:center; gap:11px; align-self:flex-start;
  min-height:34px; padding:6px 10px; border:0; border-radius:var(--r-md);
  background:none; color:var(--ink-3); font:inherit; cursor:pointer;
  transition:background .14s var(--ease), color .14s var(--ease);
}
.ds-fold:hover{ background:var(--chip); color:var(--ink); }
.ds-fold .ds-nav-name{ font-size:.8rem; font-weight:500; }
.ds-mini .ds-rail:not(:hover) .ds-fold{ align-self:center; padding:6px; }
.ds-mini .ds-rail:not(:hover) .ds-fold .ds-nav-name{ display:none; }
@media (max-width:1100px){ .ds-fold{ display:none; } }
@media (max-width:860px){ .ds-rail{ display:none; } }

.ds-grp{ display:flex; flex-direction:column; gap:2px; }
.ds-grp-lab{
  font-size:.69rem; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--ink-4); padding:0 10px 6px;
}
@media (max-width:1100px){
  .ds-rail:not(:hover) .ds-grp-lab{ padding:0; height:1px; background:var(--line-2); margin:6px 8px; overflow:hidden; color:transparent; }
}
.ds-mini .ds-rail:not(:hover) .ds-grp-lab{ padding:0; height:1px; background:var(--line-2); margin:6px 8px; overflow:hidden; color:transparent; }

.ds-nav{
  display:flex; align-items:center; gap:11px;
  min-height:38px; padding:8px 10px; border-radius:var(--r-md);
  text-decoration:none; color:var(--ink-2); cursor:pointer;
  transition:background .14s var(--ease), color .14s var(--ease);
}
.ds-nav:hover{ background:var(--chip); color:var(--ink); }
.ds-nav[aria-current]{ background:var(--blue-bg); color:var(--blue-deep); }
.ds-nav[aria-current] .ds-nav-name{ font-weight:800; }
.ds-nav svg{ flex:none; }
.ds-nav-main{ flex:1; min-width:0; line-height:1.2; display:block; }
.ds-nav-name{ display:block; font-size:.875rem; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* "Soon" is a real answer. A rail that silently omits a section leaves
   somebody wondering whether the feature exists; one that offers it and then
   404s is worse. These rows say what they are and do not move. */
.ds-nav-soon{ cursor:default; color:var(--ink-4); }
.ds-nav-soon:hover{ background:none; color:var(--ink-4); }
.ds-badge{
  flex:none; font-size:.69rem; font-weight:800;
  padding:2px 7px; border-radius:999px;
  background:var(--chip); color:var(--ink-3);
}
.ds-badge-new{ background:var(--green-bg); color:var(--green-deep); }
.ds-badge-live{ background:var(--blue-bg); color:var(--blue-deep); }

@media (max-width:1100px){
  .ds-rail:not(:hover) .ds-nav{ justify-content:center; padding:9px 0; }
  .ds-rail:not(:hover) :is(.ds-nav-main,.ds-badge,.ds-soon-chev){ display:none; }
}
.ds-mini .ds-rail:not(:hover) .ds-nav{ justify-content:center; padding:9px 0; }
.ds-mini .ds-rail:not(:hover) :is(.ds-nav-main,.ds-badge,.ds-soon-chev){ display:none; }

/* "Coming soon": one row standing for every section still being built. */
.ds-soon-btn{ width:100%; border:0; background:none; font:inherit; text-align:left; color:var(--ink-3); }
.ds-soon-chev{ display:flex; flex:none; color:var(--ink-4); transition:transform .16s var(--ease); }
.ds-soon-btn[aria-expanded="true"] .ds-soon-chev{ transform:rotate(90deg); }
.ds-soon-list{ display:flex; flex-direction:column; gap:2px; margin-top:2px; }
@media (min-width:1101px){ html:not(.ds-mini) .ds-soon-list .ds-nav{ padding-left:20px; } }
.ds-fold:focus-visible,.ds-soon-btn:focus-visible,.ds-nav:focus-visible{ outline:2px solid var(--blue); outline-offset:2px; }

/* ── the phone tab bar ──────────────────────────────────────────────── */

.ds-tabs{ display:none; }
@media (max-width:860px){
  .ds-tabs{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:40;
    background:rgba(255,255,255,.94);
    backdrop-filter:saturate(180%) blur(14px);
    -webkit-backdrop-filter:saturate(180%) blur(14px);
    border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom);
  }
  /* motion.css gives every [data-am-highlight] host position:relative and
     loads after this file, which pulled the bar out of fixed position on
     every shell page. The bar must stay fixed; the pill still positions
     against it. */
  .ds-tabs[data-am-highlight]{ position:fixed; }
  .ds-tabs a{
    flex:1; display:flex; flex-direction:column; align-items:center; gap:4px;
    padding:9px 4px 10px; text-decoration:none;
    font-size:.66rem; font-weight:600; color:var(--ink-4);
    transition:color .16s var(--ease);
  }
  .ds-tabs a[aria-current]{ color:var(--blue); }
}

/* The batch dialog (dash-shell.js): Batches and pricing links open this in
   place for a signed-in person instead of leaving for the public site. */
body.ds-locked{ overflow:hidden; }
.ds-dlg-back{ position:fixed; inset:0; z-index:80; display:flex; align-items:center; justify-content:center; padding:16px;
  background:rgba(13,20,32,.55); opacity:0; transition:opacity .2s var(--ease); }
.ds-dlg-back.open{ opacity:1; }
.ds-dlg{ position:relative; width:min(460px,100%); max-height:88vh; overflow-y:auto; background:var(--page);
  border-radius:var(--r-xl); padding:26px 24px 22px; box-shadow:0 24px 60px rgba(13,20,32,.24);
  transform:translateY(10px) scale(.985); transition:transform .26s var(--spring); }
.ds-dlg-back.open .ds-dlg{ transform:none; }
.ds-dlg:focus{ outline:none; }
.ds-dlg-x{ position:absolute; top:12px; right:12px; width:36px; height:36px; display:grid; place-items:center;
  border:0; border-radius:10px; background:transparent; color:var(--ink-3); cursor:pointer; }
.ds-dlg-x:hover{ background:var(--chip); color:var(--ink); }
.ds-dlg-kicker{ margin:0; font-size:.78rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--blue); }
.ds-dlg-title{ margin:6px 40px 0 0; font-size:1.3rem; font-weight:700; color:var(--ink); }
.ds-dlg-lede{ margin:12px 0 0; color:var(--ink-2); }
.ds-dlg-price{ display:flex; align-items:baseline; gap:8px; margin-top:14px; }
.ds-dlg-price b{ font-size:2rem; font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums; }
.ds-dlg-price span{ color:var(--ink-3); font-weight:600; }
.ds-dlg-list{ margin:14px 0 0; padding:0; list-style:none; display:grid; gap:9px; }
.ds-dlg-list li{ position:relative; padding-left:26px; color:var(--ink-2); font-size:.94rem; }
.ds-dlg-list li::before{ content:''; position:absolute; left:4px; top:.38em; width:11px; height:6px;
  border-left:2px solid var(--green-ink); border-bottom:2px solid var(--green-ink); transform:rotate(-45deg); }
.ds-dlg-actions{ display:flex; flex-wrap:wrap; gap:10px; margin-top:20px; }
.ds-dlg-actions .btn{ flex:1 1 180px; justify-content:center; }

@media (prefers-reduced-motion:reduce){
  .ds-panel,.ds-caret,.ds-nav,.ds-row{ transition:none; }
  .ds-dlg-back,.ds-dlg{ transition:none; }
}
