/* Halelu — base + app shell (shell builder). Needs tokens.css and components.css first.
   The page scrolls as a document (not inside .main__body as in the mocks), so views keep window scrolling,
   sticky headers and scrollTo. Desktop: fixed icon rail on the left, Live now bar sticky at the bottom.
   Phone (≤ 720 px): no rail; the dock (mini bar + tab bar) is fixed at the bottom with the safe area. */

html{background:var(--canvas)}
body{background:var(--canvas);color:var(--text-1);font-family:var(--font-ui)}
body.spa{display:flex;flex-direction:column;min-height:100vh;min-height:100dvh}

/* Titles: Urbanist Light (draws Hakha Chin ṭ in its own design). UI text stays on SF / Inter. */
.topbar__title,.page-title,.h1,.h2,.h-hero{font-family:var(--font-display);font-weight:300}
.h3,.card__title{font-family:var(--font-display)}

/* Keyboard skip link */
/* Waits above the screen with no shadow (a shadow there would show as a grey haze behind the logo); it gets one
   when a keyboard user tabs to it and it slides into view. */
.skip-link{position:absolute;left:12px;top:-60px;z-index:50;background:var(--surface-pop);color:var(--text-1);padding:10px 14px;border-radius:var(--r-md);box-shadow:none}
.skip-link:focus{top:calc(12px + var(--safe-top));box-shadow:var(--shadow-pop)}

/* Rings are for the keyboard only. ui.js sets html.is-pointer from a click / tap until a navigation key, which
   also covers the rings browsers draw after script focus (a dialog's first button, a menu's button). */
.is-pointer :focus-visible{outline:none !important}
.is-pointer .search:has(.search__input:focus-visible){outline:none}

/* Selected text: a neutral tint, never the system blue */
::selection{background:var(--selection)}

/* After in-app navigation app.js moves focus to the new page's title (tabindex -1): no ring on a title. */
h1[tabindex="-1"]:focus,h1[tabindex="-1"]:focus-visible{outline:none}

/* Keyboard focus never lands under the fixed bars: the browser scrolls a focused control clear of them. */
html{scroll-padding-bottom:16px}
html:has(> body.spa.is-live){scroll-padding-bottom:calc(var(--livebar-h) + var(--gap) + 24px)}

/* ================= Dialogs (ui.js openDialog / confirmDialog) = the design .dialog =================
   26 px corners, surface-pop, no lines; title in Urbanist 24, pill buttons on the right. The class names
   .modal / .modal-head / .modal-body / .modal-foot stay as hooks for page CSS (e.g. library's New song sheet). */
dialog.modal{width:min(440px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 32px - var(--safe-top) - var(--safe-bottom));margin:auto;padding:0;border:0;border-radius:var(--r-xl);background:var(--surface-pop);color:var(--text-1);box-shadow:var(--shadow-dialog);overflow:hidden}
dialog.modal[open]{display:flex;flex-direction:column}
dialog.modal.wide{width:min(980px,calc(100vw - 32px))}
dialog.modal::backdrop{background:var(--scrim)}
.modal-head{display:flex;align-items:flex-start;gap:12px;padding:24px 24px 0;flex:none;min-width:0}
.modal-head:has(.modal-close){padding-right:14px}
.modal-head .dialog__title{margin-right:auto;min-width:0;padding-top:2px;overflow-wrap:anywhere}
.modal-close{margin-top:-6px}
.modal-body{padding:14px 24px 0;overflow:auto;flex:1 1 auto;min-height:0}
.modal-body:last-child{padding-bottom:24px}
.modal-foot{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px;padding:24px;flex:none}
.dialog__msg{color:var(--text-2);font-size:var(--fs-md);line-height:1.5;overflow-wrap:anywhere}
/* On the dialog's surface-pop the grey pills and fields step up one surface, or they would not show in dark. */
dialog.modal .btn--grey{background:var(--surface-3)}
dialog.modal .btn--grey:hover{background:var(--surface-4)}
[data-theme="dark"] dialog.modal .input,[data-theme="dark"] dialog.modal .textarea{background:var(--surface-3)}
[data-theme="dark"] dialog.modal .input:hover{background:var(--surface-4)}
/* Old-style buttons a page puts in a dialog (.btn without a btn--* class, ui.js iconButton): the design pills. */
dialog.modal .btn:not([class*="btn--"]){height:var(--h-md);padding:0 18px;border:0;border-radius:var(--r-full);background:var(--surface-3);color:var(--text-1);font-size:var(--fs-md);font-weight:500}
dialog.modal .btn:not([class*="btn--"]):hover{background:var(--surface-4)}
dialog.modal .btn.btn-icon:not([class*="btn--"]){width:var(--h-md);padding:0}
dialog.modal .btn.btn-ghost:not([class*="btn--"]){background:transparent;color:var(--text-2)}
dialog.modal .btn.btn-ghost:not([class*="btn--"]):hover{background:var(--hover);color:var(--text-1)}
@media (max-width:480px){
  .modal-head{padding:20px 20px 0}
  .modal-head:has(.modal-close){padding-right:10px}
  .modal-body{padding:12px 20px 0}
  .modal-body:last-child{padding-bottom:20px}
  .modal-foot{padding:20px}
  .modal-foot .btn{flex:1 1 0}
}

/* ================= Menus (ui.js openMenu): the design .menu, placed by ui.js ================= */
body > .menu{position:fixed;z-index:200;max-width:min(340px,calc(100vw - 16px));max-height:min(420px,calc(100vh - 16px));overflow:auto;overscroll-behavior:contain}

/* ================= Toasts (ui.js toast): the design pill, bottom centre, above the Live now bar / dock ================= */
.toasts{position:fixed;z-index:300;left:50%;bottom:calc(16px + var(--safe-bottom));transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;width:min(520px,calc(100vw - 32px));pointer-events:none}
.toasts .toast{pointer-events:auto;animation:toast-in var(--t) var(--ease)}
@keyframes toast-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
body.spa.is-live .toasts{bottom:calc(var(--livebar-h) + var(--gap) + 34px + 16px)}

/* ================= Reduced motion: no slides, fades or smooth scrolling ================= */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:1ms !important;animation-iteration-count:1 !important;animation-delay:0s !important;transition-duration:1ms !important;transition-delay:0s !important;scroll-behavior:auto !important}
  .spinner{animation-duration:2.4s !important;animation-iteration-count:infinite !important}
  .btn:active,.btn-play:hover{transform:none}
}

/* ================= Shell ================= */
.app.shell{display:block;height:auto;min-height:100vh;min-height:100dvh;overflow:visible;flex:1 0 auto}
.shell .rail{position:fixed;left:0;top:0;bottom:0;width:var(--rail-w);z-index:20;background:var(--canvas);padding-top:calc(18px + var(--safe-top));overflow-y:auto;scrollbar-width:none}
.shell .rail::-webkit-scrollbar{display:none}
/* the slanted mark draws smaller than the old upright one: 32 px makes it as wide (~22 px), with the same line weight */
.shell .rail__logo .i{width:32px;height:32px;stroke-width:1.42}
.shell .rail__foot{padding-top:12px}
.shell .rail__foot .avatar{cursor:pointer}
.shell .rail__foot .avatar:hover{background:var(--surface-3)}
.shell > .main{margin-left:var(--rail-w);min-height:100vh;min-height:100dvh;padding:0 20px 0 0;display:flex;flex-direction:column}
.shell .main__body{flex:1 0 auto;display:flex;flex-direction:column;gap:var(--gap);min-height:0}
.shell .main__body > .view{flex:1 0 auto;min-width:0;display:flex;flex-direction:column;gap:var(--gap)}
.shell .main__body:focus{outline:none}

/* Page header (ui.js pageHeader): overline + 44 px light title on the left, actions on the right. */
.topbar{min-width:0}
.topbar__actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end;min-width:0}
.topbar--back{height:auto;min-height:var(--topbar-h);padding-top:16px}
.topbar--back .back{margin-bottom:10px}
.topbar--slim{height:76px}

/* Loading / empty states inside the new shell */
.shell .loading-block{display:grid;place-items:center;min-height:240px}
.spinner{width:28px;height:28px;border-radius:50%;border:2px solid var(--surface-3);border-top-color:var(--text-2);animation:shell-spin .8s linear infinite}
@keyframes shell-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spinner{animation-duration:2.4s}}
.shell .empty{padding:48px 16px;text-align:center;color:var(--text-2)}
.shell .empty h1{font-family:var(--font-display);font-weight:300;font-size:var(--fs-detail);color:var(--text-1);margin-bottom:8px}

/* Credit: "Made with ♥ by Bcl Thawng" (components.css .credit) */
.credit .heart{display:inline-block;vertical-align:-1px}

/* The dock exists only on phones */
.dock{display:none}

/* ================= Phone ================= */
@media (max-width:720px){
  .shell .rail{display:none}
  .shell > .main{margin-left:0;padding:var(--safe-top) 16px calc(var(--tabbar-h) + var(--safe-bottom) + 16px)}
  body.is-live .shell > .main{padding-bottom:calc(var(--tabbar-h) + var(--safe-bottom) + var(--minibar-h) + 24px)}
  body{font-size:var(--fs-phone)}
  .dock{display:block;padding-left:calc(8px + env(safe-area-inset-left, 0px));padding-right:calc(8px + env(safe-area-inset-right, 0px))}
  .dock .tabbar__item{min-width:0}
  .topbar{height:auto;min-height:0;padding:16px 0 16px;flex-wrap:wrap;align-items:flex-end;row-gap:12px}
  .topbar__lead{flex:1 1 auto}
  .topbar__title{font-size:var(--fs-page);white-space:normal;overflow-wrap:anywhere;line-height:1.05}
  .topbar--slim{height:auto;padding:8px 0 4px}
  .topbar .search{width:100%}
  .credit{height:auto;padding:16px 0 4px}
  /* focus and toasts stay clear of the dock (tab bar, + mini bar while live) */
  html:has(> body.spa){scroll-padding-bottom:calc(var(--tabbar-h) + var(--safe-bottom) + 24px)}
  html:has(> body.spa.is-live){scroll-padding-bottom:calc(var(--tabbar-h) + var(--minibar-h) + var(--safe-bottom) + 32px)}
  body.spa .toasts{bottom:calc(var(--tabbar-h) + var(--safe-bottom) + 20px)}
  body.spa.is-live .toasts{bottom:calc(var(--tabbar-h) + var(--minibar-h) + var(--safe-bottom) + 28px)}
}
/* Short phone screens (landscape, 200 % zoom): a compact dock, so it never takes a third of the screen. */
@media (max-width:720px) and (max-height:500px){
  :root{--tabbar-h:48px;--minibar-h:48px}
  .dock{padding-top:4px}
  .dock .minibar{margin-bottom:4px}
  .dock .minibar__thumb{display:none}
  .dock .minibar,.dock .minibar:has(> .minibar__thumb:not([hidden])){padding-left:14px}
  .tabbar{padding-top:2px}
  .tabbar__item{flex-direction:row;gap:6px}
  .tabbar__icon{width:40px;height:30px}
  .tabbar__icon .i{width:20px;height:20px}
  .shell > .main{padding-top:calc(var(--safe-top) + 4px)}
}
/* Wide but short (iPhone landscape, 200 % zoom on a laptop): rail and Live now bar get compact; the rail and
   the page keep clear of the camera cut-out and the home indicator. */
@media (min-width:721px){
  .shell .rail{width:calc(var(--rail-w) + env(safe-area-inset-left, 0px));padding-left:env(safe-area-inset-left, 0px);padding-bottom:calc(16px + var(--safe-bottom))}
  .shell > .main{margin-left:calc(var(--rail-w) + env(safe-area-inset-left, 0px));padding-right:calc(20px + env(safe-area-inset-right, 0px))}
}
@media (min-width:721px) and (max-height:560px){
  :root{--livebar-h:56px}
  .shell .rail{padding-top:calc(10px + var(--safe-top))}
  .shell .rail__logo{margin-bottom:8px}
  .shell .rail__nav{gap:4px}
  .shell .rail__item{height:52px}
  .shell .rail__foot{gap:6px;padding-top:8px}
}
@media (min-width:721px){
  .only-phone{display:none !important}
}
@media (max-width:720px){
  .only-desk{display:none !important}
}

/* Big light titles hide their overflow for the "…" at a tight line height, which cut off descenders
   (the g in "Songs", y, p, the dot under ṭ). Give them room inside the clip without moving the layout. */
body .topbar__title,body .playlist-head__title,body .ed-title,body .remote__title,body .rm-set-name{padding-bottom:.18em;margin-bottom:-.18em}

